Summary
Direct filesystem updates on Roland D-20 disks can select out-of-bounds blocks and rewrite existing filenames incorrectly.
Reproduction
fluxengine putfile -c rolandd20 -f drive:1 \ -l TESTSND.333 -p TESTSND2.333
The disk uses the rolandd20 profile and a Greaseweazle-connected 80-track PC drive.
Observed behavior
- The initial write failed with:
Error: invalid filesystem: sector 972 is out of bounds
The D-20 format has 78 tracks × 12 sectors, so sector 972 is outside its filesystem.
- After the allocation issue was worked around, a directory rewrite changed existing names while retaining their original byte counts and file data:
TESTALL.111 -> TESTALL.11.1
TESTSONG.222 -> TESTSONG.2.22
TESTSND.333 -> TESTSND.33.3
TESTRHY.444 -> TESTRHY.44.4
The newly added name TESTSND2.333 was correct.
Likely causes and proposed fixes
Allocation bounds
RolandFsFilesystem::init() derives its allocation count from the drive-probed sector count. A physical probe can expose extra tracks that are not part of the D-20 filesystem, allowing allocation to target an invalid block.
For the current Roland GCRDOS layout, allocation should be bounded by the tracks arranged around the directory track:
_filesystemBlocks = _config.directory_track() * 2;
_midBlock = _config.directory_track();
A more general option would be an explicit filesystem-block-count field in RolandFsProto.
Filename encoding
RolandDirent::filename should remain the human-readable name. It is currently sometimes pre-mangled before directory serialization, while existing entries are human-readable after mounting. Rewriting then puts the literal dot in the fixed 13-byte on-disk field, shifting the extension when the disk is read again.
Suggested changes:
// putFile
auto de = std::make_shared<RolandDirent>(path.front());
// moveFile
de->rename(newName.front());
// rewriteDirectory
const std::string mangledFilename = mangleFilename(de->filename);
bw.append(mangledFilename);
bw.pad(13 - mangledFilename.size(), '_');
This keeps file data and directory metadata separate and preserves names through directory rewrites.
Summary
Direct filesystem updates on Roland D-20 disks can select out-of-bounds blocks and rewrite existing filenames incorrectly.
Reproduction
fluxengine putfile -c rolandd20 -f drive:1 \ -l TESTSND.333 -p TESTSND2.333The disk uses the
rolandd20profile and a Greaseweazle-connected 80-track PC drive.Observed behavior
The D-20 format has 78 tracks × 12 sectors, so sector 972 is outside its filesystem.
The newly added name
TESTSND2.333was correct.Likely causes and proposed fixes
Allocation bounds
RolandFsFilesystem::init()derives its allocation count from the drive-probed sector count. A physical probe can expose extra tracks that are not part of the D-20 filesystem, allowing allocation to target an invalid block.For the current Roland GCRDOS layout, allocation should be bounded by the tracks arranged around the directory track:
_filesystemBlocks = _config.directory_track() * 2; _midBlock = _config.directory_track();A more general option would be an explicit filesystem-block-count field in
RolandFsProto.Filename encoding
RolandDirent::filenameshould remain the human-readable name. It is currently sometimes pre-mangled before directory serialization, while existing entries are human-readable after mounting. Rewriting then puts the literal dot in the fixed 13-byte on-disk field, shifting the extension when the disk is read again.Suggested changes:
This keeps file data and directory metadata separate and preserves names through directory rewrites.