ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
fw_if_fs_posix_stream.c
Go to the documentation of this file.
1
23
24#ifndef RA8_OFF_TARGET
25#error "port/posix is host-only and must never be compiled or linked into target firmware."
26#endif
27
28#include <errno.h>
29#include <fcntl.h>
30#include <stdint.h> // ra8-keep-include: `uint8_t` used directly
31#include <sys/stat.h>
32#include <unistd.h>
33
34#include "fw_if_fs.h" // ra8-keep-include: `fw_fs_stream_iface_t` backend interface used directly
35#include "fw_if_fs_backend.h"
37#include "ra8_attributes.h" // ra8-keep-include: `RA8_INTERNAL` and `RA8_PRIV` used directly
38#include "ra8_err.h" // ra8-keep-include: `ra8_err_t` used directly
39
40#ifndef O_CLOEXEC
42#define O_CLOEXEC (0)
43#endif
44
45#ifndef O_NOFOLLOW
47#define O_NOFOLLOW (0)
48#endif
49
50/* see header for full description */
52{
53 if (mode == k_fw_fs_open_read) {
54 *out_flags = O_RDONLY | O_CLOEXEC | O_NOFOLLOW;
55 return k_ra8_ok;
56 }
57 if (mode == k_fw_fs_open_write_truncate) {
58 *out_flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW;
59 return k_ra8_ok;
60 }
61 if (mode == k_fw_fs_open_append) {
62 *out_flags = O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC | O_NOFOLLOW;
63 return k_ra8_ok;
64 }
65 if (mode == k_fw_fs_open_create_new) {
66 *out_flags = O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW;
67 return k_ra8_ok;
68 }
70}
71
72/* see header for full description */
74 const char* path,
76 void* file_state,
77 uint32_t state_bytes)
78{
79 if (state_bytes < sizeof(posix_file_state_t)) {
80 return k_ra8_err_no_mem;
81 }
82 int flags = 0;
83 const ra8_err_t mapped = internal_open_flags(mode, &flags);
84 if (mapped != k_ra8_ok) {
85 return mapped;
86 }
88 int parent_fd = -1;
89 char leaf[k_posix_component_cap];
90 const ra8_err_t parent = priv_fs_posix_parent_open(state, path, &parent_fd, leaf);
91 if (parent != k_ra8_ok) {
92 return parent;
93 }
94 const int opened = openat(parent_fd, leaf, flags, (mode_t)k_posix_file_mode);
95 const int saved_errno = errno;
96 const ra8_err_t closed = priv_fs_posix_close_fd(&parent_fd);
97 if (opened < 0) {
98 return priv_fs_posix_errno(saved_errno);
99 }
100 if (closed != k_ra8_ok) {
101 int owned = opened;
102 return priv_fs_posix_close_fd_preserve(&owned, closed);
103 }
104 struct stat meta = {};
105 if (fstat(opened, &meta) != 0) {
106 int owned = opened;
108 }
109 if (!S_ISREG(meta.st_mode)) {
110 int owned = opened;
112 }
113 ((posix_file_state_t*)file_state)->fd = opened;
114 return k_ra8_ok;
115}
116
117/* see header for full description */
119internal_read(void* ctx, void* file_state, uint8_t* dst, uint32_t cap, uint32_t* out_read)
120{
121 (void)ctx;
122 const int fd = ((posix_file_state_t*)file_state)->fd;
123 ssize_t got = -1;
124 int saved = 0;
125 do {
126 got = read(fd, dst, (size_t)cap);
127 /* Capture errno in the statement after the call that set it: nothing may
128 * run in between, and the retry test then reads a plain int. */
129 saved = (got < 0) ? errno : 0;
130 } while (saved == EINTR);
131 if (got < 0) {
132 return priv_fs_posix_errno(saved);
133 }
134 *out_read = (uint32_t)got;
135 return k_ra8_ok;
136}
137
138/* see header for full description */
140 void* file_state,
141 const uint8_t* src,
142 uint32_t len,
143 uint32_t* out_written)
144{
145 (void)ctx;
146 const int fd = ((posix_file_state_t*)file_state)->fd;
147 while (*out_written < len) {
148 const uint32_t remaining = len - *out_written;
149 const ssize_t wrote = write(fd, &src[*out_written], (size_t)remaining);
150 /* Capture errno in the statement after the call that set it (see the read
151 * loop above); the two tests below then read a plain int. */
152 const int saved = (wrote < 0) ? errno : 0;
153 if (wrote < 0) {
154 if (saved == EINTR) {
155 continue;
156 }
157 return priv_fs_posix_errno(saved);
158 }
159 if (wrote == 0) {
160 return k_ra8_fail;
161 }
162 *out_written += (uint32_t)wrote;
163 }
164 return k_ra8_ok;
165}
166
167/* see header for full description */
168RA8_PRIV ra8_err_t priv_fs_posix_seek(void* ctx, void* file_state, uint64_t offset)
169{
170 (void)ctx;
171 if (offset > (uint64_t)INT64_MAX) {
173 }
174 const int fd = ((posix_file_state_t*)file_state)->fd;
175 if (lseek(fd, (off_t)offset, SEEK_SET) < 0) {
176 return priv_fs_posix_errno(errno);
177 }
178 return k_ra8_ok;
179}
180
181/* see header for full description */
182RA8_INTERNAL static ra8_err_t internal_tell(void* ctx, void* file_state, uint64_t* out_offset)
183{
184 (void)ctx;
185 const int fd = ((posix_file_state_t*)file_state)->fd;
186 const off_t offset = lseek(fd, 0, SEEK_CUR);
187 if (offset < 0) {
188 return priv_fs_posix_errno(errno);
189 }
190 *out_offset = (uint64_t)offset;
191 return k_ra8_ok;
192}
193
194/* see header for full description */
195RA8_PRIV ra8_err_t priv_fs_posix_size(void* ctx, void* file_state, uint64_t* out_size)
196{
197 (void)ctx;
198 const int fd = ((posix_file_state_t*)file_state)->fd;
199 struct stat meta = {};
200 if (fstat(fd, &meta) != 0) {
201 return priv_fs_posix_errno(errno);
202 }
203 *out_size = (uint64_t)meta.st_size;
204 return k_ra8_ok;
205}
206
207/* see header for full description */
208RA8_PRIV ra8_err_t priv_fs_posix_sync(void* ctx, void* file_state)
209{
210 (void)ctx;
211 const int fd = ((posix_file_state_t*)file_state)->fd;
212 if (fsync(fd) != 0) {
213 return priv_fs_posix_errno(errno);
214 }
215 return k_ra8_ok;
216}
217
218/* see header for full description */
219RA8_PRIV ra8_err_t priv_fs_posix_close(void* ctx, void* file_state)
220{
221 (void)ctx;
222 return priv_fs_posix_close_fd(&((posix_file_state_t*)file_state)->fd);
223}
224
225/* see header for full description */
227{
229 static const fw_fs_stream_iface_t k_stream_iface = {
230 .open = priv_fs_posix_open,
231 .read = internal_read,
232 .write = priv_fs_posix_write,
233 .seek = priv_fs_posix_seek,
234 .tell = internal_tell,
235 .size = priv_fs_posix_size,
236 .sync = priv_fs_posix_sync,
237 .close = priv_fs_posix_close,
238 };
239 return &k_stream_iface;
240}
static uint32_t internal_read(void)
Read current GPT counter ticks, or return UINT32_MAX on err.
Definition main.c:150
Architecture-neutral filesystem namespace, stream, and transaction ports.
Backend-author interface for binding concrete filesystem ports.
ra8_err_t priv_fs_posix_parent_open(fw_fs_posix_state_t *state, const char *path, int *out_parent_fd, char *out_leaf)
Resolve a canonical path's parent without following any symlink.
#define O_NOFOLLOW
Zero fallback paired with explicit no-follow metadata validation.
#define O_CLOEXEC
Zero fallback when the host lacks close-on-exec open flags.
ra8_err_t priv_fs_posix_close_fd(int *fd)
Close exactly once and invalidate the caller's descriptor.
ra8_err_t priv_fs_posix_close_fd_preserve(int *fd, ra8_err_t primary)
Close one owned descriptor while preserving a primary status.
ra8_err_t priv_fs_posix_errno(int value)
Map one captured errno value into ra8_err_t.
ra8_err_t priv_fs_posix_seek(void *ctx, void *file_state, uint64_t offset)
Seek a POSIX descriptor to an unsigned absolute offset.
ra8_err_t priv_fs_posix_close(void *ctx, void *file_state)
Close and consume one caller-owned POSIX file state.
ra8_err_t priv_fs_posix_sync(void *ctx, void *file_state)
Flush file contents and metadata through POSIX fsync.
ra8_err_t priv_fs_posix_write(void *ctx, void *file_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
Complete POSIX short writes while reporting any accepted prefix.
ra8_err_t priv_fs_posix_size(void *ctx, void *file_state, uint64_t *out_size)
Report a POSIX descriptor's current file length.
@ k_posix_file_mode
Owner-only created-file mode.
@ k_posix_component_cap
Component buffer including NUL.
ra8_err_t priv_fs_posix_open(void *ctx, const char *path, fw_fs_open_mode_t mode, void *file_state, uint32_t state_bytes)
Open one confined regular file into caller workspace.
ra8_err_t priv_fs_posix_seek(void *ctx, void *file_state, uint64_t offset)
Seek a POSIX descriptor to an unsigned absolute offset.
ra8_err_t priv_fs_posix_close(void *ctx, void *file_state)
Close and consume one caller-owned POSIX file state.
ra8_err_t priv_fs_posix_sync(void *ctx, void *file_state)
Flush file contents and metadata through POSIX fsync.
ra8_err_t priv_fs_posix_write(void *ctx, void *file_state, const uint8_t *src, uint32_t len, uint32_t *out_written)
Complete POSIX short writes while reporting any accepted prefix.
ra8_err_t priv_fs_posix_size(void *ctx, void *file_state, uint64_t *out_size)
Report a POSIX descriptor's current file length.
const fw_fs_stream_iface_t * priv_fs_posix_stream_iface(void)
Borrow the immutable POSIX byte-stream operation table.
ra8_err_t priv_fs_posix_open(void *ctx, const char *path, fw_fs_open_mode_t mode, void *file_state, uint32_t state_bytes)
Open one confined regular file into caller workspace.
static ra8_err_t internal_tell(void *ctx, void *file_state, uint64_t *out_offset)
static ra8_err_t internal_open_flags(fw_fs_open_mode_t mode, int *out_flags)
File-local contracts for the hosted POSIX byte-stream operations.
static ra8_err_t internal_read(void *ctx, void *file_state, uint8_t *dst, uint32_t cap, uint32_t *out_read)
static ra8_err_t internal_tell(void *ctx, void *file_state, uint64_t *out_offset)
struct fw_fs_stream_iface fw_fs_stream_iface_t
fw_fs_open_mode_t
Open intent for fw_fs_open.
@ k_fw_fs_open_create_new
Create only when leaf is absent.
@ k_fw_fs_open_append
Create/append, write-only.
@ k_fw_fs_open_read
Existing file, read-only.
@ k_fw_fs_open_write_truncate
Create/truncate, write-only.
-proof
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_fail
Generic unspecified failure.
Definition ra8_err.h:133
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Caller-owned POSIX adapter state.
POSIX state placed in caller file workspace.