|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
exFAT open-for-write: create, truncate, append, and the survey between. More...
#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_fs.h"#include "ra8_fs_fat_internal.h"Go to the source code of this file.
Functions | |
| static void | internal_exfat_seed_handle (ra8_fs_file_t *file, ra8_fs_mount_t *m, const exfat_setpos_t *head, uint32_t count, ra8_fs_mode_t mode) |
| Zero every field of a freshly claimed handle and bind it to its set. | |
| static ra8_err_t | internal_exfat_survey_alloc (ra8_fs_file_t *file) |
| Count a file's clusters and find its tail. | |
| static ra8_err_t | internal_exfat_truncate (ra8_fs_file_t *file, const uint8_t *strm) |
| Release a file's clusters and rewrite its entry set empty, in place. | |
| static ra8_err_t | internal_exfat_writable_set (uint32_t count) |
| Reject an entry set this adapter cannot correctly rewrite. | |
| static ra8_err_t | internal_exfat_open_found (ra8_fs_mount_t *handle, ra8_fs_mode_t mode, const exfat_setpos_t *head, uint32_t count, const uint8_t *file_e, const uint8_t *strm, ra8_fs_file_t **out_file) |
| Open an existing name for writing: truncate it, or park at its end. | |
| static ra8_err_t | internal_exfat_open_created (ra8_fs_mount_t *handle, const exfat_dir_t *dir, const uint16_t *name, uint32_t nlen, ra8_fs_mode_t mode, ra8_fs_file_t **out_file) |
| Create a name that does not exist and open the empty file it names. | |
| ra8_err_t | priv_exfat_open_write (ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file) |
| Open an exFAT file for writing: create, truncate, or position to append. | |
exFAT open-for-write: create, truncate, append, and the survey between.
ra8_fs_open() used to answer k_ra8_err_not_supported for both writing modes on an exFAT volume, so the one way to put bytes on such a card was a whole-file creator that needed the payload in RAM and one contiguous run on disk (#602). This file is the other half of the fix: it turns a name into an open, writable handle, in the three shapes the API promises.
A path that resolves to a DIRECTORY is refused in both modes: a truncate would hand the clusters holding its contents back to the volume and orphan every file inside it (#604).
References (every shorthand citation in this file):
Definition in file ra8_fs_fat_exfat_openw.c.
|
static |
Create a name that does not exist and open the empty file it names.
Claims the file slot BEFORE writing the directory entry, so a full file table is discovered while the directory is still untouched – the other order leaves a real, empty file behind on a call that returned an error.
| [in,out] | handle | Mounted exFAT volume. |
| [in] | dir | Directory the name is created in. |
| [in] | name | Leaf name as UTF-16 code units (no leading '/'). |
| [in] | nlen | Number of units in name. |
| [in] | mode | Writing mode to record on the handle. |
| [out] | out_file | Receives the open handle. |
| k_ra8_ok | The name exists as an empty file and is open. |
| k_ra8_err_no_mem | The file table is full, or the root directory has no run of free slots big enough for the set. |
| k_ra8_err_* | Backend read/write failure. |
nlen is at most k_exfat_name_cap. dir holds a zero-length set for that name. Definition at line 387 of file ra8_fs_fat_exfat_openw.c.
References ra8_fs_file_t::in_use, internal_exfat_seed_handle(), k_ra8_err_no_mem, k_ra8_ok, ra8_fs_file_t::mount, priv_alloc_file_slot(), and priv_exfat_link().
Referenced by priv_exfat_open_write().
|
static |
Open an existing name for writing: truncate it, or park at its end.
Refuses a directory before anything else, claims a file slot, seeds it from the Stream entry, and then branches on the mode. On any failure after the slot is claimed the slot is handed back, so a refused open never costs one of the four handles. A ValidDataLength above DataLength is clamped rather than believed: it is not a prefix length if it is longer than the file.
| [in,out] | handle | Mounted exFAT volume. |
| [in] | mode | k_ra8_fs_mode_write or k_ra8_fs_mode_append. |
| [in] | head | Position of the set's File entry. |
| [in] | count | Entry count of the set. |
| [in] | file_e | The set's 32-byte File entry. |
| [in] | strm | The set's 32-byte Stream-extension entry. |
| [out] | out_file | Receives the open handle. |
| k_ra8_ok | The handle is open and positioned. |
| k_ra8_err_invalid_arg | The name is a directory. |
| k_ra8_err_no_mem | The file table is full. |
| k_ra8_err_not_supported | The set is larger than this adapter rewrites. |
| k_ra8_err_* | Bitmap, FAT, or backend failure. |
mode. Definition at line 300 of file ra8_fs_fat_exfat_openw.c.
References ra8_fs_file_t::cur_cluster, ra8_fs_file_t::first_cluster, ra8_fs_file_t::in_use, internal_exfat_seed_handle(), internal_exfat_survey_alloc(), internal_exfat_truncate(), internal_exfat_writable_set(), k_exfat_attr_directory, k_exfat_attr_read_only, k_exfat_off_file_attr, k_exfat_off_strm_valid, k_exfat_secflag_no_fat, k_exfat_strm_off_clus, k_exfat_strm_off_dlen, k_exfat_strm_off_flags, k_ra8_err_access_denied, k_ra8_err_invalid_arg, k_ra8_err_no_mem, k_ra8_fs_mode_write, k_ra8_ok, ra8_fs_file_t::mount, ra8_fs_file_t::no_fat_chain, ra8_fs_file_t::offset, priv_alloc_file_slot(), priv_rd32(), priv_rd64(), ra8_fs_file_t::size_bytes, ra8_fs_file_t::valid_bytes, and ra8_fs_file_t::walk_cache_cluster.
Referenced by priv_exfat_open_write().
|
static |
Zero every field of a freshly claimed handle and bind it to its set.
One place decides what "an open exFAT file that owns nothing" is, so a later field cannot be added to ra8_fs_file_t and left uninitialised on one of the three open paths.
| [out] | file | Slot to initialise. |
| [in] | m | Owning mount. |
| [in] | head | Position of the set's File entry. |
| [in] | count | Entry count of the set (1 + SecondaryCount). |
| [in] | mode | Open mode to record. |
file, m and head are non-NULL. head came from priv_exfat_find_set or priv_exfat_link. file is in use, owns no clusters, and is positioned at byte 0. Definition at line 71 of file ra8_fs_fat_exfat_openw.c.
References exfat_setpos_t::cluster, and exfat_setpos_t::index.
Referenced by internal_exfat_open_created(), and internal_exfat_open_found().
|
static |
Count a file's clusters and find its tail.
An append has to know where the allocation ENDS before it can add to it, and the entry set does not record that: a contiguous file implies it from DataLength, and a chained one only reveals it by walking the FAT. The walk is bounded by the volume's cluster count, so a corrupted chain that loops terminates instead of hanging.
A chained file may own MORE clusters than its length needs (another implementation may have pre-allocated), and the walk finds them, so an append reuses that space instead of asking the bitmap for more.
| [in,out] | file | Handle whose stream fields are already populated. |
| k_ra8_ok | alloc_clusters and tail_cluster are set. |
| k_ra8_err_protocol_error | The chain points below the first data cluster. |
| k_ra8_err_* | FAT read failure. |
file is non-NULL with first_cluster, size_bytes and no_fat_chain taken from the on-disk Stream entry. Definition at line 134 of file ra8_fs_fat_exfat_openw.c.
References ra8_fs_mount_t::count_of_clusters, k_cluster_first_data, k_ra8_err_protocol_error, k_ra8_ok, priv_cluster_bytes(), priv_fat_get(), and priv_is_eoc().
Referenced by internal_exfat_open_found().
|
static |
Release a file's clusters and rewrite its entry set empty, in place.
What k_ra8_fs_mode_write means on an existing name. The entry set is kept – so the file's creation stamp and its position in the directory survive – and only its allocation and both lengths go.
| [in,out] | file | Open handle to empty. |
| [in] | strm | The file's Stream entry as read from the volume. |
| k_ra8_ok | The file is zero-length and owns no clusters. |
| k_ra8_err_* | Bitmap or backend failure. |
file and strm are non-NULL; the handle is in use. Definition at line 196 of file ra8_fs_fat_exfat_openw.c.
References k_ra8_ok, priv_exfat_flush_set(), and priv_exfat_free_clusters().
Referenced by internal_exfat_open_found().
|
static |
Reject an entry set this adapter cannot correctly rewrite.
Two refusals, both honest limits rather than guesses.
A set SHORTER than ::k_exfat_set_min_entries is not a file: exFAT
spec sec 7.4 requires a File entry, a Stream entry and at least one
Name entry, and the flush rewrites the first two by position. A set
claiming no secondaries would send that rewrite at the entry BEFORE
the Stream entry -- on a fresh volume, the allocation-bitmap entry
-- so the shape has to be checked, not assumed.
A set LONGER than ::k_exfat_set_writable carries a name past this
adapter's cap, and rewriting only the part that fits would leave a
SetChecksum computed over the wrong number of entries.
A `DataLength` above 4 GiB is no longer one of the refusals: the
whole length model is 64-bit now, so a file past 4 GiB opens,
appends and truncates like any other -- carrying such files is the
reason exFAT exists (#676).
| [in] | count | Entry count of the set (1 + SecondaryCount). |
| k_ra8_ok | The set is one this adapter can own. |
| k_ra8_err_protocol_error | The set is too short to be a file. |
| k_ra8_err_not_supported | The set has more entries than it can rewrite. |
count came from the File entry's SecondaryCount. Definition at line 253 of file ra8_fs_fat_exfat_openw.c.
References k_exfat_set_min_entries, k_exfat_set_writable, k_ra8_err_not_supported, k_ra8_err_protocol_error, and k_ra8_ok.
Referenced by internal_exfat_open_found().
| ra8_err_t priv_exfat_open_write | ( | ra8_fs_mount_t * | handle, |
| const char * | path, | ||
| ra8_fs_mode_t | mode, | ||
| ra8_fs_file_t ** | out_file ) |
Open an exFAT file for writing: create, truncate, or position to append.
The exFAT half of ra8_fs_open for the two writing modes. It locates the name's entry set, refuses a directory (a truncate would free the clusters holding its contents), and then either truncates the file in place – keeping its entry, and therefore its creation stamp – or seeks to DataLength for an append. A name that does not exist is created as a zero-length entry set, so the handle is usable before a single byte has been written.
| [in,out] | handle | Mounted exFAT volume. |
| [in] | path | Flat root-level name (ASCII); leading '/' stripped. |
| [in] | mode | k_ra8_fs_mode_write or k_ra8_fs_mode_append. |
| [out] | out_file | Receives the open handle. |
| k_ra8_ok | File open and positioned for mode. |
| k_ra8_err_invalid_arg | Empty or over-long name, or path is a directory. |
| k_ra8_err_no_mem | File table full, or no free directory slot. |
| k_ra8_err_not_supported | The existing entry set is larger than this adapter can rewrite. |
| k_ra8_err_* | Backend read/write failure. |
handle, path and out_file are non-NULL; the mount is in use. mode is a writing mode; read opens never reach here. Definition at line 412 of file ra8_fs_fat_exfat_openw.c.
References internal_exfat_open_created(), internal_exfat_open_found(), k_exfat_entry_bytes, k_exfat_name_cap, k_exfat_set_max_entries, k_ra8_err_invalid_arg, k_ra8_err_no_mem, k_ra8_err_not_found, k_ra8_ok, priv_exfat_find_set(), priv_exfat_name_to_units(), and priv_exfat_resolve_parent().
Referenced by priv_exfat_open().