Close package fs review findings: readRange bounds, picker ext, non-ASCII tests

Cap readRange's allocation and reject size_t overflow instead of truncating;
re-append .rsbank when the export picker omits it; add cafe coverage for
writeFileExclusive and writeLandedFile; loop write() on EINTR.
This commit is contained in:
2026-08-02 08:44:29 -04:00
parent edfd7ead4d
commit 655159ceac
10 changed files with 97 additions and 17 deletions
+11 -3
View File
@@ -53,8 +53,12 @@ belong to the verbs.
"Did this call create it" is structural: only exclusively-created paths are
recorded, resolved absolute at record time so a later CWD change cannot re-aim the
delete. "Did anything ever reference it" is a **contract the import verb must
honour**: it MUST call `markIndexCommitted()` at the moment it commits the index,
after which `rollback()` refuses and `writeLandedFile` refuses.
honour**: it MUST call `markIndexCommitted()` only AFTER the index write has
returned success — calling it before, then having that write fail, strands the
landed files with no index entry and a journal that now refuses to roll them
back — after which `rollback()` refuses and `writeLandedFile` refuses. (Destroying
an armed journal without calling either does NOT roll it back — see
`LandedFileJournal`'s own doc comment.)
- **Both pickers ride `GetUserFileName`** — mode 1 for import, mode 0 for export.
There is no platform split and no fallback: `main.cpp` defines `REAPERAPI_IMPLEMENT`
without `REAPERAPI_MINIMAL` and aborts the extension load if any single name fails
@@ -80,7 +84,11 @@ belong to the verbs.
pair format but are `[verify — DAW]` on all three platforms — neither picker is
exercised outside a live REAPER session. `GetUserFileName` also takes no owner
window, so dialog parenting is REAPER's to do; the superseded Win32 path passed
`GetMainHwnd()` explicitly.
`GetMainHwnd()` explicitly. Also `[verify — DAW]`: whether mode 0's picker appends
an extension from `extension_list` when the user omits one — `pickPackageSavePath`
re-appends `.rsbank` itself so the returned path is correct regardless of how that
lands (the superseded Win32 path had `ofn.lpstrDefExt` for this; `GetUserFileName`
has no equivalent parameter).
- `pickPackageSavePath`'s `suggestedPath` doubles as the dialog's starting directory
when it is a full path. The verbs should seed it from the project directory —
passing a bare name leaves the dialog on REAPER's process working directory, which