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#include "cdc_views/ImageView.h"
18#include "host_str_conv.h"
19
20#include <cstdio>
21#include <cstring>
22#include <string>
23#include <sys/stat.h>
24#include <dirent.h>
25
26extern "C" void* plg_get_active_plugin(void);
27
28namespace {
29
30constexpr size_t MAX_NAME_LEN = 64;
31
33bool nameOk(const char* name)
34{
35 if (!name || !*name) return false;
36 size_t n = std::strlen(name);
37 if (n > MAX_NAME_LEN || name[0] == '.') return false;
38 for (size_t i = 0; i < n; ++i) {
39 char c = name[i];
40 bool ok = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
41 (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-';
42 if (!ok) return false;
43 }
44 return true;
45}
46
48int resolveDir(std::string& out)
49{
50 auto* plugin = static_cast<cdc::plugin_manager::Plugin*>(plg_get_active_plugin());
51 if (!plugin) return HOST_ERR_GENERIC;
52 if (!plugin->manifest().capabilities.vfat) return HOST_ERR_NO_CAPABILITY;
53
54 std::string dataRoot =
55 std::string(cdc::plugin_manager::PluginStorage::basePath()) + "/data";
56 mkdir(dataRoot.c_str(), 0755);
57 out = dataRoot + "/" + plugin->id();
58 mkdir(out.c_str(), 0755);
59 return HOST_OK;
60}
61
63int resolvePath(const char* name, std::string& out)
64{
65 std::string dir;
66 int rc = resolveDir(dir);
67 if (rc != HOST_OK) return rc;
68 if (!nameOk(name)) return HOST_ERR_INVALID_ARG;
69 out = dir + "/" + name;
70 return HOST_OK;
71}
72
73} // namespace
74
75extern "C" {
76
77int host_fs_write(const char* name, const uint8_t* data, size_t len)
78{
79 if (!data && len > 0) return HOST_ERR_INVALID_ARG;
80 std::string path;
81 int rc = resolvePath(name, path);
82 if (rc != HOST_OK) return rc;
83
84 auto f = cdc::core::openFile(path.c_str(), "wb");
85 if (!f) return HOST_ERR_GENERIC;
86 if (len > 0 && std::fwrite(data, 1, len, f.get()) != len) return HOST_ERR_GENERIC;
87 return HOST_OK;
88}
89
90int host_fs_read(const char* name, uint8_t* buf, size_t* len)
91{
92 if (!buf || !len) return HOST_ERR_INVALID_ARG;
93 std::string path;
94 int rc = resolvePath(name, path);
95 if (rc != HOST_OK) return rc;
96
97 auto f = cdc::core::openFile(path.c_str(), "rb");
98 if (!f) return HOST_ERR_NOT_FOUND;
99 *len = std::fread(buf, 1, *len, f.get());
100 return HOST_OK;
101}
102
103int host_fs_remove(const char* name)
104{
105 std::string path;
106 int rc = resolvePath(name, path);
107 if (rc != HOST_OK) return rc;
108 return (std::remove(path.c_str()) == 0) ? HOST_OK : HOST_ERR_NOT_FOUND;
109}
110
111int host_fs_size(const char* name, size_t* out)
112{
113 if (!out) return HOST_ERR_INVALID_ARG;
114 std::string path;
115 int rc = resolvePath(name, path);
116 if (rc != HOST_OK) return rc;
117
118 struct stat st;
119 if (stat(path.c_str(), &st) != 0) return HOST_ERR_NOT_FOUND;
120 *out = static_cast<size_t>(st.st_size);
121 return HOST_OK;
122}
123
124int host_fs_list(char* out, size_t* out_len)
125{
126 if (!out_len) return HOST_ERR_INVALID_ARG;
127 std::string dir;
128 int rc = resolveDir(dir);
129 if (rc != HOST_OK) return rc;
130
131 DIR* d = opendir(dir.c_str());
132 if (!d) return HOST_ERR_NOT_FOUND;
133
134 size_t written = 0;
135 const size_t max = (out ? *out_len : 0);
136 for (struct dirent* e = readdir(d); e != nullptr; e = readdir(d)) {
137 if (e->d_name[0] == '.') continue;
138 size_t need = std::strlen(e->d_name) + 1;
139 if (out && (written + need) <= max) {
140 std::memcpy(out + written, e->d_name, need - 1);
141 out[written + need - 1] = '\n';
142 }
143 written += need;
144 }
145 closedir(d);
146 *out_len = written;
147 return HOST_OK;
148}
149
150int host_fs_view(const char* name)
151{
152 std::string path;
153 int rc = resolvePath(name, path);
154 if (rc != HOST_OK) return rc;
155
156 auto f = cdc::core::openFile(path.c_str(), "rb");
157 if (!f) return HOST_ERR_NOT_FOUND;
158
159 // Match the on-screen text viewer's capacity (InfoView buffer).
160 constexpr size_t VIEW_MAX = 2048;
161 std::string content;
162 content.resize(VIEW_MAX);
163 size_t n = std::fread(&content[0], 1, VIEW_MAX - 1, f.get());
164 content.resize(n);
165 // Files and filenames are UTF-8; host_ui_push_info converts to display.
166 return host_ui_push_info(name, content.c_str());
167}
168
169int host_fs_view_image(const char* name)
170{
171 std::string path;
172 int rc = resolvePath(name, path);
173 if (rc != HOST_OK) return rc;
174
175 auto f = cdc::core::openFile(path.c_str(), "rb");
176 if (!f) return HOST_ERR_NOT_FOUND;
177
178 constexpr size_t IMG_MAX = 512 * 1024;
179 std::string buf;
180 buf.resize(IMG_MAX);
181 size_t n = std::fread(&buf[0], 1, IMG_MAX, f.get());
182 buf.resize(n);
183
184 std::string title = cdc::plugin_manager::toDisplay(name);
185 cdc::ui::showImage(title.c_str(),
186 reinterpret_cast<const uint8_t*>(buf.data()), buf.size());
187 return HOST_OK;
188}
189
191{
192 std::string path;
193 int rc = resolvePath(name, path);
194 if (rc != HOST_OK) return rc;
195
196 auto f = cdc::core::openFile(path.c_str(), "rb");
197 if (!f) return HOST_ERR_NOT_FOUND;
198
199 constexpr size_t MD_MAX = 64 * 1024;
200 std::string content;
201 content.resize(MD_MAX);
202 size_t n = std::fread(&content[0], 1, MD_MAX - 1, f.get());
203 content.resize(n);
204
205 std::string title = cdc::plugin_manager::toDisplay(name);
206 std::string body = cdc::plugin_manager::toDisplay(content.c_str());
207 cdc::ui::showMarkdown(title.c_str(), body.c_str(), body.size());
208 return HOST_OK;
209}
210
211} // 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. "/vfat".
int host_ui_push_info(const char *title, const char *body)
Show a scrollable info screen with title and body.
int host_fs_view_markdown(const char *name)
Render and show one of the plugin's own Markdown files in the scrollable text viewer.
int host_fs_view_image(const char *name)
Decode and show one of the plugin's own image files (PNG/JPEG) on the e-paper, dithered and scaled to...
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)
Internal UTF-8 <-> CP437 helpers for the plugin host API boundary.
FilePtr openFile(const char *path, const char *mode) noexcept
Open a FILE* and wrap it in a FilePtr.
Definition Raii.h:87
std::string toDisplay(const char *utf8)
Decode a UTF-8 (with optional HTML entities) string into CP437 bytes.
MarkdownView * showMarkdown(const char *title, const char *src, size_t len)
Parses and shows a Markdown source on the view stack.
ImageView * showImage(const char *title, const uint8_t *data, size_t len)
Decodes and shows an image on the view stack.