macOS ARM support for f3probe#279
Open
mgarciaisaia wants to merge 10 commits into
Open
Conversation
Add a Darwin implementation of the libdevs.c block-device backend so f3probe
builds and runs natively on arm64 macOS. libprobe.c (the validated algorithm)
is byte-for-byte unchanged; all changes are in the device backend and the build.
Key finding that shaped the port: f3probe uses create_block_device(.., RT_NONE)
and libprobe.c never calls dev_reset() — so the Linux USBDEVFS_RESET is NOT used
by f3probe (it is an f3brew feature, out of scope). f3probe defeats caches with
unbuffered raw I/O + overwhelm_cache, so no IOKit/USB reset is needed.
Darwin backend (guarded by #ifdef __APPLE__ / #ifdef __linux__):
- bdev_open: open /dev/rdiskN + fcntl(F_NOCACHE) instead of O_DIRECT
- size: DKIOCGETBLOCKCOUNT x DKIOCGETBLOCKSIZE instead of BLKGETSIZE64/BLKSSZGET
- write flush: F_FULLFSYNC + DKIOCSYNCHRONIZECACHE instead of fsync/FADV_DONTNEED
- create_block_device: parse/validate the disk path (reject slices),
diskutil unmountDisk the whole disk, RT_NONE only
- all libudev/USBDEVFS machinery wrapped in #ifdef __linux__
Makefile: drop -ludev on non-Linux; on macOS build only f3probe among the extra
tools; resolve argp via `brew --prefix argp-standalone`.
Also adds spike.c (Phase-1 cache-defeat de-risking test), PORT-LOG.md (audit
trail), and README-macOS.md (build/usage + validation runbook).
IMPORTANT: this was authored on a Linux container with no compiler and no
hardware. It is NOT compiled and NOT validated against real cards. f3probe is a
fraud-detection tool; its verdicts must not be trusted until the Phase 1 spike
and Phase 4 correctness battery in PORT-LOG.md / README-macOS.md pass on a Mac.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The spike wrote pattern B to the LAST announced block, but on a wraparound fake the last block rarely aliases onto block 0 (aliasing is modulo the real size), and limbo-type fakes don't corrupt low blocks at all — so the test could report "no aliasing" on a genuinely fake card and make the cross-check inconclusive. Add --real-size=BYTES: write B at the first announced block past the real capacity (the wrap boundary), which physical-aliases onto block 0 on a clean wraparound fake. Default unchanged (last block) but now clearly labelled as possibly-not-aliasing. Also clarify the VERDICT and the physical cross-check text (power-cycle the card; node may change on reinsert). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…NCHRONIZECACHE
Phase-1 spike run on macOS showed fcntl(fd, F_FULLFSYNC) failing with ENOTTY
("inappropriate ioctl for device") on /dev/rdiskN: F_FULLFSYNC applies to
regular files, not raw device nodes. The write itself succeeded; only the flush
aborted. f3probe's bdev_write_blocks would have failed identically.
Flush the drive's write cache with DKIOCSYNCHRONIZECACHE instead (the analogue
of Linux fsync on a block device). The raw node is opened with F_NOCACHE, so the
OS buffer cache is already bypassed. Tolerate ENOTTY/ENOTSUP (readers that don't
implement SYNCHRONIZE CACHE) with a one-time warning and surface other errno.
Also a positive signal: the raw write to block 0 worked, so the buffer
page-alignment concern did not materialise on this reader.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spike (post-flush-fix) on the known-limbo card: block 0 in-process == dd after reseat (A); limbo block #249856 written with B read back as zeros in-process and zeros via dd after power-cycle — the discarded write never returned from cache. No cache lied on this reader. Recipe confirmed: rdisk + F_NOCACHE + DKIOCSYNCHRONIZECACHE, no USB reset. Definitive proof (f3probe + overwhelm_cache matching ground truth) still pending. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f3probe reported the limbo card as "damaged / 0 blocks" in 0.5ms: its first write (at the last announced block, offset ~2TB) failed and the non-verbose probe hid the errno behind a silenced callback. Add a Darwin diagnostic on the raw read/write error paths printing offset, block range, errno, and the buffer's alignment vs pagesize and blocksize, to distinguish an alignment bug (EINVAL + unaligned buffer) from the device/USB stack rejecting a high-LBA access (EIO/ENXIO at a huge offset). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
getpagesize() is a legacy BSD call hidden when _POSIX_C_SOURCE is defined (libdevs.c sets it), causing -Wimplicit-function-declaration -> error on macOS. sysconf(_SC_PAGESIZE) is core POSIX and always declared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
macOS f3probe verdict is identical to Linux ground truth: limbo, usable 122 MB / 249856 blocks, last good 249855, module 2^41, announced 1.95 TB. macOS found cache size 0 vs Linux 512 MB (verdict unaffected; consistent with the spike showing no cache lie on this reader). Caveat recorded: the immediately-prior run returned "damaged/0 blocks" from the same I/O code (first write at the ~2TB last block failed twice). Non-determinism to characterize in Phase 5; direction is safe (intermittent damaged, not a false good) but unquantified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5/5 f3probe runs on the limbo card returned identical limbo/122MB; the earlier one-off "damaged" did not recur (safe-direction transient at the extreme LBA). Update the README banner from "UNVALIDATED" to the accurate scope: validated on one limbo card + one reader against Linux ground truth, deterministic, physical read confirmed; NOT proven for genuine cards, other archetypes, other readers, or 4K media. Fill in the results table and honest limits statement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Under sudo (uid 0) an EACCES on /dev/rdiskN fell through to a bare "Permission denied": the only EACCES hint was gated behind getuid(), and there was no read-only/write-protect detection at all. A locked SD card (physical lock switch) thus produced a confusing error even though the cause is mundane. - Add darwin_media_is_write_protected() (O_RDONLY open + DKIOCISWRITABLE, #ifdef-guarded, true only when definitely locked) and darwin_warn_write_protected(). - EACCES now branches: write-protected -> lock-switch hint; non-root -> existing run-as-root hint; root -> new message naming write-protect + Full Disk Access (root bypasses classic UNIX DAC, so those are the real causes). Proactive post-open check catches bridges that open RW yet reject writes. The err() path restores the saved open_errno. - Document as a PORT-LOG field finding and a README-macOS troubleshooting note. Not yet built on macOS; verify lock ON -> clear message, lock OFF -> probe proceeds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
They may be interesting to someone checking the port, but they don't make sense in the upstream repo if merged.
Author
|
I will probably not be able to maintain this code - I even already returned the faulty SD card, so I can't reproduce issues anymore. I totally understand this not getting merge - I mostly wanted to put it out there so folks in #8 may benefit from it. It worked for me. |
Owner
|
Hi @mgarciaisaia, Thank you for posting this PR. As you've educately guessed, I won't merge it. But your PR is a step towards eventually making |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR makes f3probe compile in macOS running ARM.
It was entirely vibe-coded with Claude 4.8 at xhigh effort, and I was able to verify with 2 SD cards (a legitimate 128GB one, and a fake, limbo 2TB-that's-actually-122MB one), comparing against f3probe runnign in an Ubuntu 24.04 VM running in VirtualBox in this same computer.
I don't know if it works on an Intel macOS.
See #8