1mod magic;
5
6use std::{fmt, path::Path};
7
8pub enum FsKind {
9 Fat32,
10 Unknown,
11}
12
13impl fmt::Display for FsKind {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 match self {
16 FsKind::Fat32 => write!(f, "FAT32"),
17 FsKind::Unknown => write!(f, "Unknown"),
18 }
19 }
20}
21
22#[cfg(unix)]
23pub fn detect(path: &Path) -> rustix::io::Result<FsKind> {
24 let stat = rustix::fs::statfs(path)?;
25
26 #[cfg(target_os = "linux")]
27 let data = stat.f_type;
28
29 #[cfg(target_os = "macos")]
30 let data = stat.f_fstypename;
31
32 let kind = match data {
33 magic::FAT32 => FsKind::Fat32,
34 _ => FsKind::Unknown,
35 };
36
37 Ok(kind)
38}
39
40#[cfg(windows)]
41pub fn detect(path: &Path) -> windows::core::Result<FsKind> {
42 use std::os::windows::ffi::OsStrExt;
43 use windows::Win32::Foundation::MAX_PATH;
44 use windows::Win32::Storage::FileSystem::{GetVolumeInformationW, GetVolumePathNameW};
45 use windows::core::PCWSTR;
46
47 let path_wide: Vec<u16> = path
49 .as_os_str()
50 .encode_wide()
51 .chain(std::iter::once(0))
52 .collect();
53
54 let mut volume_path = [0u16; MAX_PATH as usize];
56 unsafe {
57 GetVolumePathNameW(PCWSTR(path_wide.as_ptr()), &mut volume_path)?;
58 }
59
60 let mut fs_name_buffer = [0u16; 8];
61 unsafe {
62 GetVolumeInformationW(
63 PCWSTR(volume_path.as_ptr()),
64 None,
65 None,
66 None,
67 None,
68 Some(&mut fs_name_buffer),
69 )?;
70 }
71
72 let kind = match fs_name_buffer {
73 magic::FAT32 => FsKind::Fat32,
74 _ => FsKind::Unknown,
75 };
76
77 Ok(kind)
78}