What happens
Called from the Mac App Store app, which runs in the App Sandbox, baken_export::export writes every track, export.pdb and My Settings, and then returns Error::Io with Operation not permitted (os error 1). The Report is lost with it, so the caller cannot say what was written, although the stick is complete. With prune the run stops partway through Contents, after some unreferenced files have already been deleted.
Cause
Measured on macOS 26 with small sandboxed apps signed Apple Development:
- Every file a sandboxed app creates carries
com.apple.quarantine (and com.apple.provenance). removexattr of the quarantine attribute answers EPERM, and LSFileQuarantineEnabled = false in Info.plist does not stop it being set.
- On FAT those attributes are stored in a
._X AppleDouble file. Inside the sandbox, unlinking ._X while X exists and carries quarantine is EPERM: it is treated as an attribute operation on X.
- So
remove_apple_double fails on the sidecar of the first file this run wrote, and prune_tree fails the same way, because the ._X of a kept file is not in wanted.
- Unlinking
X itself works, and the volume then drops ._X on its own.
The CLI never meets this: it is not sandboxed, so its files carry no quarantine.
A real run
One export of a 35-track playlist from the app (CDJ-safe, My Settings, prune) to a FAT32 stick that rekordbox had exported to the day before: all 35 tracks and export.pdb written, then the EPERM. The run left 145 ._ files behind, and prune had stopped partway. The same stick already held 13 ._ files in Contents from rekordbox's own export the day before, so sidecars are normal on a stick that rekordbox writes from a Mac.
Proposal, for 4.2.1
- In
remove_apple_double, an EPERM removing a ._ file is not an error: skip the file and count it in Report (for example apple_double_kept), so a caller can say how many were left. Other errors stay errors.
- In
prune_tree, do not try to remove ._X when X is kept. When X is removed, its sidecar goes with it.
After that a sandboxed caller gets its Report, and prune works there too, since unlinking the data files is allowed.
Open question
The code says Linux-based players trip on ._ files, but I found no hardware report behind it. A sandboxed app cannot remove them at all, so it would help to know whether a player behaves any differently with them on the stick. That is a question for the #116 testers.
Reproducing
The CLI cannot reproduce this. A sandboxed build of the app writing to a FAT32 disk image (hdiutil create -fs "MS-DOS FAT32" -layout MBRSPUD) does.
What happens
Called from the Mac App Store app, which runs in the App Sandbox,
baken_export::exportwrites every track,export.pdband My Settings, and then returnsError::IowithOperation not permitted (os error 1). TheReportis lost with it, so the caller cannot say what was written, although the stick is complete. Withprunethe run stops partway throughContents, after some unreferenced files have already been deleted.Cause
Measured on macOS 26 with small sandboxed apps signed Apple Development:
com.apple.quarantine(andcom.apple.provenance).removexattrof the quarantine attribute answers EPERM, andLSFileQuarantineEnabled = falsein Info.plist does not stop it being set.._XAppleDouble file. Inside the sandbox, unlinking._XwhileXexists and carries quarantine is EPERM: it is treated as an attribute operation onX.remove_apple_doublefails on the sidecar of the first file this run wrote, andprune_treefails the same way, because the._Xof a kept file is not inwanted.Xitself works, and the volume then drops._Xon its own.The CLI never meets this: it is not sandboxed, so its files carry no quarantine.
A real run
One export of a 35-track playlist from the app (CDJ-safe, My Settings, prune) to a FAT32 stick that rekordbox had exported to the day before: all 35 tracks and
export.pdbwritten, then the EPERM. The run left 145._files behind, and prune had stopped partway. The same stick already held 13._files inContentsfrom rekordbox's own export the day before, so sidecars are normal on a stick that rekordbox writes from a Mac.Proposal, for 4.2.1
remove_apple_double, an EPERM removing a._file is not an error: skip the file and count it inReport(for exampleapple_double_kept), so a caller can say how many were left. Other errors stay errors.prune_tree, do not try to remove._XwhenXis kept. WhenXis removed, its sidecar goes with it.After that a sandboxed caller gets its
Report, and prune works there too, since unlinking the data files is allowed.Open question
The code says Linux-based players trip on
._files, but I found no hardware report behind it. A sandboxed app cannot remove them at all, so it would help to know whether a player behaves any differently with them on the stick. That is a question for the #116 testers.Reproducing
The CLI cannot reproduce this. A sandboxed build of the app writing to a FAT32 disk image (
hdiutil create -fs "MS-DOS FAT32" -layout MBRSPUD) does.