Fix the package fs seam: UTF-8 paths, GetUserFileName pickers, exclusive-create landing, rollback arm/disarm

Both pickers now ride GetUserFileName (mode 0/1); the "no save picker" premise was false.
Landing uses O_EXCL so the create is the existence check, not a TOCTOU pair.
This commit is contained in:
2026-08-02 08:15:12 -04:00
parent 41a3016e63
commit edfd7ead4d
11 changed files with 532 additions and 253 deletions
+10 -10
View File
@@ -1,8 +1,7 @@
// shell/package/package_pickers — the two package file pickers, and they are
// deliberately asymmetric: import rides REAPER's own read picker
// (GetUserFileNameForRead, both platforms); export goes native — Win32
// GetSaveFileNameW / SWELL BrowseForSaveFile — because the always-present REAPER
// surface offers no save picker. Do not symmetrize; the rationale is in the TU.
// shell/package/package_pickers — the two package file pickers, both on REAPER's own
// GetUserFileName (mode 1 = existing file, mode 0 = new file). No native/platform
// split: the SDK's save mode is not optional on any build that can load this
// extension. Paths in and out are UTF-8, per the REAPER API contract.
#pragma once
@@ -10,12 +9,13 @@
namespace reasampler {
// REAPER's read picker. True with outAbsPath set iff the user chose a file.
// True with outAbsPath set iff the user chose a file.
bool pickPackageForImport(std::string& outAbsPath);
// Native save picker, pre-filled with suggestedFileName (a bare name, e.g.
// "MyBank.rsbank"). True with outAbsPath set iff the user chose a destination; the
// dialog's own overwrite confirm has already run by then.
bool pickPackageSavePath(const std::string& suggestedFileName, std::string& outAbsPath);
// suggestedPath is a bare file name ("MyBank.rsbank") or a full path — a full one
// also seeds the dialog's starting directory, which is how a caller keeps the picker
// off REAPER's process working directory. True with outAbsPath set iff the user chose
// a destination; the dialog's own overwrite confirm has already run by then.
bool pickPackageSavePath(const std::string& suggestedPath, std::string& outAbsPath);
} // namespace reasampler