Skip to content

Find microSD cards on Linux, through the mount table (#106) - #112

Merged
ww8l merged 1 commit into
mainfrom
issue-106-linux-card-detection
Aug 22, 2026
Merged

Find microSD cards on Linux, through the mount table (#106)#112
ww8l merged 1 commit into
mainfrom
issue-106-linux-card-detection

Conversation

@ww8l

@ww8l ww8l commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Closes #106 — and it is no longer read-from-source: Tim reproduced it on a real Linux box, where the app detects no card and he has to navigate to it by hand.

The bug

mounted_roots() split two ways — Windows, or else — and Linux landed in the else:

std::fs::read_dir("/Volumes")          // macOS only
    .map(|rd| rd.flatten().map(|e| e.path()).collect())
    .unwrap_or_default()               // Linux: Err -> empty, silently

/Volumes does not exist on Linux, so the list was always empty. It is the only source of card locations, so no microSD card was ever detected: FT5D, ID-52 and TH-D75 all unusable on a platform with published installers, with nothing indicating why. Cable radios were unaffected.

The fix

Linux has no single directory to point at — udisks2 uses /media/<user>/<label> on Debian/Ubuntu and /run/media/<user>/<label> on Fedora/Arch, and a hand-mounted card is wherever the operator put it. So instead of guessing at conventions, read /proc/mounts and filter by filesystem type: every radio here writes its card as FAT or exFAT, and no Linux system volume is either (fuseblk included, because exfat-fuse reports itself that way).

  • /boot is dropped. The EFI system partition is vfat and every UEFI machine has one, so a plain "FAT means removable" rule would offer /boot/efi as a card on every Linux install.
  • Mount points are unescaped. The kernel writes space/tab/newline/backslash as three-digit octal, so a card labelled MY CARD arrives as MY\040CARD and a path built from it verbatim would not exist. Unescaped bytes-first so an accented label survives; a backslash that is not a valid escape is left alone rather than guessed at.
  • The three-way split is explicit #[cfg] arms, with compile_error! for anything else. A fourth platform now fails to build rather than silently inheriting another OS's convention — that inheritance is this bug.

Verification

  • npm run ci green on macOS: 433 tests, clippy -D warnings clean.
  • Three new tests parse a real Ubuntu mount table: the card is found under /media/<user>, /run/media/<user> and a hand mount under /mnt; /, /proc, /sys, a tmpfs and /boot/efi are all rejected; malformed lines are skipped rather than half-parsed. The parser is compiled into the tests on every OS, so this is checked on the machines that do not have the bug.
  • Not yet confirmed against the Linux box itself — the mount table there has not been read, and no Linux build of this branch has been run. CI's ubuntu leg proves it compiles, not that it finds Tim's card.

🤖 Generated with Claude Code

https://claude.ai/code/session_013cZgbB4FwqZ3Z4cdHt6vMH

`mounted_roots()` handled Windows and macOS and let Linux fall through to
the macOS branch, where `read_dir("/Volumes")` returns an error that
`unwrap_or_default()` threw away. On Linux the list was therefore always
empty: no card was ever detected, FT5D / ID-52 / TH-D75 were unusable, and
nothing said why. Reproduced on a real Linux box — the operator has to
navigate to the card by hand.

Linux has no `/Volumes` equivalent to guess at. udisks2 mounts under
`/media/<user>/<label>` on Debian and Ubuntu, `/run/media/<user>/<label>`
on Fedora and Arch, and a hand-mounted card is wherever the operator put
it — so read `/proc/mounts` and filter by filesystem instead. Every radio
here writes its card as FAT or exFAT and no Linux system volume is either;
the EFI system partition is the one vfat volume every UEFI machine has, so
/boot is dropped rather than offered as a card.

Mount points are octal-escaped by the kernel, so `MY CARD` arrives as
`MY\040CARD` and a path built from it verbatim would not exist. Unescaped
here, bytes-first so an accented label survives.

The three-way split is now explicit `#[cfg]` arms: a fourth platform fails
to build instead of silently inheriting whichever branch it lands in, which
is the whole mechanism of this bug.

The parser is compiled into the tests on every OS, so `cargo test` checks it
on the machines that do not have the bug.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013cZgbB4FwqZ3Z4cdHt6vMH
@ww8l
ww8l merged commit 1a569a0 into main Aug 22, 2026
3 checks passed
@ww8l
ww8l deleted the issue-106-linux-card-detection branch August 22, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

microSD card detection never finds a card on Linux

1 participant