Compile the mount-table reader only where there is a mount table

`platform_volumes` has been gated to Linux since it was written, but the
eight items it is built from were not, so every Android build compiled a
`/proc/mounts` parser it could never call and then printed eight dead-code
warnings about it. Real warnings hide in that kind of noise.

Gated per item rather than moved into a module, because the file already
draws the line that way one function above and two patterns for one idea
is worse than a repeated attribute.

The tests go with them. They parse a mount table and assert on names like
`mmcblk0p1`, so they are as Linux-bound as the code they exercise, and
`Path` turns out to be too -- only the reader borrows one, where `Volume`
owns its own.

Android now builds dr-plat with no warnings at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-27 12:17:25 +02:00
co-authored by Claude Opus 5
parent 721efbc371
commit 9997623df4
+15 -2
View File
@@ -27,7 +27,10 @@
//! directory is reported alongside and weighted more heavily than the flag:
//! a volume with `DCIM` on it is a camera card whatever sysfs believes.
use std::path::{Path, PathBuf};
use std::path::PathBuf;
// Only the mount-table reader below borrows a path; `Volume` owns one.
#[cfg(target_os = "linux")]
use std::path::Path;
/// Somewhere a card might be.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -136,6 +139,7 @@ fn platform_volumes() -> Vec<Volume> {
}
/// One line of the mount table.
#[cfg(target_os = "linux")]
#[derive(Debug, Clone, PartialEq, Eq)]
struct Mount {
device: String,
@@ -147,6 +151,7 @@ struct Mount {
///
/// Split out from the reading so it can be tested against real tables without
/// a card plugged in — which is the only way this file is testable at all.
#[cfg(target_os = "linux")]
fn parse_mounts(table: &str) -> Vec<Mount> {
table
.lines()
@@ -169,6 +174,7 @@ fn parse_mounts(table: &str) -> Vec<Mount> {
/// A card is very often labelled with a space in it — `EOS DIGITAL` is what
/// Canon writes — and mounted at `/run/media/duncan/EOS\040DIGITAL`. Without
/// this the path does not exist and the card is invisible.
#[cfg(target_os = "linux")]
fn unescape(field: &str) -> String {
let mut out = String::with_capacity(field.len());
let bytes = field.as_bytes();
@@ -192,6 +198,7 @@ fn unescape(field: &str) -> String {
///
/// Excludes the pseudo-filesystems, which is most of the table, and anything
/// not backed by a block device. A card reader always is.
#[cfg(target_os = "linux")]
fn is_candidate(m: &Mount) -> bool {
const FILESYSTEMS: &[&str] = &[
// What cameras format cards as, in practice: FAT32 below 32 GB,
@@ -204,6 +211,7 @@ fn is_candidate(m: &Mount) -> bool {
}
/// Whether the desktop automounted this, which means it already decided.
#[cfg(target_os = "linux")]
fn under_media_dir(mount_point: &Path) -> bool {
let s = mount_point.to_string_lossy();
s.starts_with("/run/media/") || s.starts_with("/media/") || s.starts_with("/mnt/media/")
@@ -217,6 +225,7 @@ fn under_media_dir(mount_point: &Path) -> bool {
/// lose only the `pN` suffix — strip naively and `mmcblk0p1` becomes
/// `mmcblk`, which does not exist, and every SD card in an internal reader
/// reports itself fixed.
#[cfg(target_os = "linux")]
fn device_is_removable(device: &str) -> Option<bool> {
let name = device.strip_prefix("/dev/")?;
let disk = whole_disk(name);
@@ -225,6 +234,7 @@ fn device_is_removable(device: &str) -> Option<bool> {
}
/// The whole-disk name a partition belongs to.
#[cfg(target_os = "linux")]
fn whole_disk(partition: &str) -> String {
// `mmcblk0p1` -> `mmcblk0`, `nvme0n1p3` -> `nvme0n1`: these spell the
// partition with a `p`, and the disk name legitimately ends in a digit.
@@ -243,6 +253,7 @@ fn whole_disk(partition: &str) -> String {
}
/// What to call a volume in a list.
#[cfg(target_os = "linux")]
fn label_for(mount_point: &Path) -> String {
mount_point
.file_name()
@@ -250,7 +261,9 @@ fn label_for(mount_point: &Path) -> String {
.unwrap_or_else(|| mount_point.to_string_lossy().to_string())
}
#[cfg(test)]
// Reading `/proc/mounts` and naming block devices is what these test, so
// they are as Linux-bound as the code above.
#[cfg(all(test, target_os = "linux"))]
mod tests {
use super::*;