39#define O_DIRECTORY (0)
48typedef enum : uint32_t {
70 size_t length =
strlen(text);
71 while (offset < length) {
72 const ssize_t written =
write(STDERR_FILENO, &text[offset], length - offset);
73 if ((written < 0) && (errno == EINTR)) {
79 offset += (size_t)written;
91 }
while (value != 0U);
92 for (
size_t i = 0U; i < digits; ++i) {
93 forward[i] = reverse[digits - i - 1U];
95 forward[digits] =
'\0';
119 if (offset > (uint64_t)INT64_MAX || length > ((uint64_t)INT64_MAX - offset)) {
123 while (done < length) {
124 size_t request = length - done;
125 if (request > (
size_t)SSIZE_MAX) {
126 request = (size_t)SSIZE_MAX;
128 const ssize_t got = pread(fd, &bytes[done], request, (off_t)(offset + done));
129 if ((got < 0) && (errno == EINTR)) {
160 if (offset > (uint64_t)INT64_MAX || length > ((uint64_t)INT64_MAX - offset)) {
164 while (done < length) {
165 size_t request = length - done;
166 if (request > (
size_t)SSIZE_MAX) {
167 request = (size_t)SSIZE_MAX;
169 const ssize_t put = pwrite(fd, &bytes[done], request, (off_t)(offset + done));
170 if ((put < 0) && (errno == EINTR)) {
202 uint64_t* out_offset,
209 const uint64_t offset = lba * disk->
block_size;
210 const size_t bytes = (size_t)count * disk->
block_size;
211 if (offset > (uint64_t)INT64_MAX || bytes > ((uint64_t)INT64_MAX - offset)) {
214 *out_offset = offset;
244 if (disk ==
nullptr || buffer ==
nullptr || disk->
io_failed ||
280 if (disk ==
nullptr || buffer ==
nullptr || disk->
io_failed ||
311 if (disk ==
nullptr || block_count ==
nullptr || block_size ==
nullptr) {
339 const size_t length =
strlen(path);
343 size_t slash = length;
344 while (slash > 0U && path[slash - 1U] !=
'/') {
347 const size_t leaf_bytes = length - slash;
351 (void)
memcpy(leaf, &path[slash], leaf_bytes);
352 leaf[leaf_bytes] =
'\0';
353 if (
strcmp(leaf,
".") == 0 ||
strcmp(leaf,
"..") == 0) {
359 }
else if (slash == 1U) {
363 const size_t parent_bytes = slash - 1U;
364 (void)
memcpy(parent, path, parent_bytes);
365 parent[parent_bytes] =
'\0';
389 static const char s_prefix[] =
".mkfontimg.tmp.";
391 size_t offset =
sizeof(
s_prefix) - 1U;
393 uint64_t values[2] = {process, attempt};
394 for (uint8_t field = 0U; field < 2U; ++field) {
399 }
while (values[field] != 0U);
403 while (digits > 0U) {
404 out[offset++] = reverse[--digits];
406 out[offset++] = (field == 0U) ?
'.' :
'\0';
412 uint64_t block_count,
418 if (block_count == 0U || block_size == 0U || block_count > (UINT64_MAX / block_size) ||
422 const uint64_t image_bytes = block_count * block_size;
423 if (image_bytes > (uint64_t)INT64_MAX) {
438 if (host->
image_fd >= 0 || errno != EEXIST) {
447 if (ftruncate(host->
image_fd, (off_t)image_bytes) != 0) {
463 if (host ==
nullptr || bytes ==
nullptr || host->
image_fd < 0 ||
490 const long modified_nsec = metadata->st_mtimespec.tv_nsec;
491 const long changed_nsec = metadata->st_ctimespec.tv_nsec;
493 const long modified_nsec = metadata->st_mtim.tv_nsec;
494 const long changed_nsec = metadata->st_ctim.tv_nsec;
497 .inode = metadata->st_ino,
498 .size = (uint64_t)metadata->st_size,
499 .modified_sec = metadata->st_mtime,
500 .modified_nsec = modified_nsec,
501 .changed_sec = metadata->st_ctime,
502 .changed_nsec = changed_nsec};
548 uint64_t minimum_bytes,
549 uint64_t maximum_bytes,
557 struct stat metadata = {};
558 if (fstat(fd, &metadata) != 0 || !S_ISREG(metadata.st_mode) || metadata.st_size < 0 ||
559 (uint64_t)metadata.st_size < minimum_bytes || (uint64_t)metadata.st_size > maximum_bytes) {
588 uint64_t offset = 0U;
590 while (ok && offset < identity->size) {
591 uint32_t take = (uint32_t)(identity->
size - offset);
592 if (take > (uint32_t)
sizeof(chunk)) {
593 take = (uint32_t)
sizeof(chunk);
599 struct stat after = {};
600 if (fstat(input_fd, &after) != 0) {
632 uint64_t offset = 0U;
634 while (ok && offset < identity->size) {
635 uint32_t take = (uint32_t)(identity->
size - offset);
636 if (take > (uint32_t)
sizeof(source)) {
637 take = (uint32_t)
sizeof(source);
642 memcmp(source, copied, take) == 0;
645 struct stat after = {};
646 if (fstat(input_fd, &after) != 0) {
679 const char* input_path,
680 const char* card_name,
681 uint64_t minimum_bytes,
682 uint64_t maximum_bytes,
686 if (!
internal_input_open(input_path, minimum_bytes, maximum_bytes, &input_fd, out_identity)) {
697 if (close(input_fd) != 0) {
725 const char* input_path,
726 const char* card_name,
727 uint64_t minimum_bytes,
728 uint64_t maximum_bytes,
736 (void)close(input_fd);
740 uint64_t card_size = 0U;
750 if (close(input_fd) != 0) {
758 const char* input_path,
759 const char* card_name,
760 uint64_t minimum_bytes,
761 uint64_t maximum_bytes,
783 *out_bytes = identity.
size;
static ra8_err_t internal_disk_write(void *ctx, uint64_t lba, uint32_t count, const uint8_t *buffer)
Write blocks into the sparse unpublished image.
static bool internal_block_range(const mk_disk_t *disk, uint64_t lba, uint32_t count, uint64_t *out_offset, size_t *out_bytes)
Translate one sector range into bounded hosted byte coordinates.
static ra8_err_t internal_disk_read(void *ctx, uint64_t lba, uint32_t count, uint8_t *buffer)
Read blocks from the sparse unpublished image.
#define O_DIRECTORY
No-op directory-open fallback for hosts lacking the flag.
static ra8_err_t internal_disk_capacity(void *ctx, uint64_t *block_count, uint32_t *block_size)
Report the fixed card-image geometry.
#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.
static host_input_identity_t internal_identity(const struct stat *metadata)
Capture all mutation-sensitive fields from one successful fstat.
void priv_mkfontimg_diag(const char *text)
Write one complete best-effort diagnostic fragment to standard error.
static ra8_err_t internal_disk_write(void *ctx, uint64_t lba, uint32_t count, const uint8_t *buffer)
Write sectors into the sparse unpublished image.
bool priv_mkfontimg_host_seed(mkfontimg_host_t *host, const uint8_t *bytes, uint32_t length)
Seed exact bytes at the beginning of the temporary image.
bool priv_mkfontimg_host_begin(const char *final_path, uint64_t block_count, uint32_t block_size, mkfontimg_host_t *host)
Create, size, and bind one private sibling-temporary image.
static bool internal_identity_equal(const host_input_identity_t *left, const host_input_identity_t *right)
Compare two initialized input identities without inspecting padding.
static bool internal_input_open(const char *path, uint64_t minimum_bytes, uint64_t maximum_bytes, int *out_fd, host_input_identity_t *identity)
Open and validate one non-symlink regular input.
static ra8_err_t internal_disk_read(void *ctx, uint64_t lba, uint32_t count, uint8_t *buffer)
Read sectors from the sparse unpublished image.
host_limit_t
Fixed I/O, naming, and formatting bounds.
@ k_host_stream_chunk
Bounded copy chunk bytes.
@ k_host_temp_attempts
Exclusive-create retry bound.
@ k_host_decimal_base
Decimal conversion radix.
@ k_host_decimal_digits
Maximum uint64_t digits.
@ k_host_create_mode
Hosted output creation mode.
bool priv_mkfontimg_host_commit(mkfontimg_host_t *host)
Sync and atomically publish a complete temporary image.
static bool internal_mkfontimg_verify(ra8_fs_mount_t *mount, const char *input_path, const char *card_name, uint64_t minimum_bytes, uint64_t maximum_bytes, const host_input_identity_t *identity)
Reopen the host input and card file and verify byte-for-byte identity.
void priv_mkfontimg_diag_u64(uint64_t value)
Write one unsigned decimal value to standard error without stdio.
void priv_mkfontimg_host_abort(mkfontimg_host_t *host)
Close and unlink an unpublished temporary image.
bool priv_mkfontimg_host_copy(const mkfontimg_host_t *host, ra8_fs_mount_t *mount, const char *input_path, const char *card_name, uint64_t minimum_bytes, uint64_t maximum_bytes, uint64_t *out_bytes)
Stream one stable host input into a card file and verify it by reread.
static ra8_err_t internal_disk_capacity(void *ctx, uint64_t *block_count, uint32_t *block_size)
Report the fixed sparse-image geometry.
static bool internal_pread_exact(int fd, uint64_t offset, uint8_t *bytes, size_t length)
Read an exact positioned byte range with bounded retries.
static bool internal_stream(int input_fd, const host_input_identity_t *identity, ra8_fs_file_t *card)
Stream the first pass from host input to one new card file.
static bool internal_temp_name(char out[k_mkfontimg_host_name_cap], uint64_t process, uint32_t attempt)
Build one collision-resistant hidden temporary leaf.
static bool internal_split_output(const char *path, char parent[k_mkfontimg_host_path_cap], char leaf[k_mkfontimg_host_name_cap])
Split one output path into bounded parent and leaf components.
static bool internal_pwrite_exact(int fd, uint64_t offset, const uint8_t *bytes, size_t length)
Write an exact positioned byte range with bounded retries.
static bool internal_block_range(const mkfontimg_disk_t *disk, uint64_t lba, uint32_t count, uint64_t *out_offset, size_t *out_bytes)
Translate one sector range to a representable byte range.
static bool internal_compare(int input_fd, const host_input_identity_t *identity, ra8_fs_file_t *card)
Compare a second host-input pass with the generated card file.
static bool internal_mkfontimg_write(ra8_fs_mount_t *mount, const char *input_path, const char *card_name, uint64_t minimum_bytes, uint64_t maximum_bytes, host_input_identity_t *out_identity)
Open the host input and stream it into a fresh card file.
Module-private bounded host-storage composition for mkfontimg.
@ k_mkfontimg_host_name_cap
Hosted leaf capacity.
@ k_mkfontimg_host_path_cap
Hosted path capacity.
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_fail
Generic unspecified failure.
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
int renameat(int old_dir_fd, const char *old_path, int new_dir_fd, const char *new_path)
Rename one directory-relative path to another atomically.
int strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_write(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Write len bytes; allocate new clusters from FAT free-space scan as needed.
ra8_err_t ra8_fs_size(const ra8_fs_file_t *file, uint64_t *out_bytes)
Report the file's size in bytes (64-bit on exFAT, #676).
ra8_err_t ra8_fs_read(ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
Read up to max_len bytes; advance the cluster chain on cluster crossings.
ra8_err_t ra8_fs_open(ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file)
Open or create a file by path, 8.3 or long.
ra8_err_t ra8_fs_close(ra8_fs_file_t *file)
Close an open file, stamping its final modification time.
@ k_ra8_fs_mode_read
Read-only, must exist.
@ k_ra8_fs_mode_write
Truncate (or create) for writing.
static const uint8_t s_prefix[k_ra8_net_provision_prefix_bytes]
Exact protocol prefix, including the first field separator.
Descriptor-backed block-device state bound into ra8_fs.
bool io_failed
Sticky positioned-I/O failure.
int fd
Temporary image descriptor.
uint32_t block_size
Bytes per sector.
uint64_t block_count
Addressable sectors.
Caller-owned sibling-temporary and block-backend binding.
ra8_fs_backend_t backend
Portable FS facade.
mkfontimg_disk_t disk
Bound block state.
int image_fd
Image descriptor.
int directory_fd
Parent descriptor.
char final_name[k_mkfontimg_host_name_cap]
Destination leaf.
char temp_name[k_mkfontimg_host_name_cap]
Temporary leaf.
bool temp_exists
Temp cleanup guard.
Block-device interface that ra8_fs runs on top of.
Cached parse of one mounted FAT volume.