lfs_core/device_id/
unix.rs1use {
2 super::{
3 ParseDeviceIdError,
4 ParseDeviceIdSnafu,
5 },
6 crate::Error,
7 snafu::prelude::*,
8 std::{
9 fmt,
10 fs,
11 os::unix::fs::MetadataExt,
12 path::Path,
13 str::FromStr,
14 },
15};
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
19pub struct DeviceId {
20 pub major: u32,
21 pub minor: u32,
22}
23
24impl fmt::Display for DeviceId {
25 fn fmt(
26 &self,
27 f: &mut fmt::Formatter,
28 ) -> fmt::Result {
29 write!(f, "{}:{}", self.major, self.minor)
30 }
31}
32
33impl FromStr for DeviceId {
34 type Err = ParseDeviceIdError;
35 fn from_str(string: &str) -> Result<Self, Self::Err> {
37 (|| {
38 let mut parts = string.split(':').fuse();
39 match (parts.next(), parts.next(), parts.next()) {
40 (Some(major), Some(minor), None) => {
41 let major = major.parse().ok()?;
42 let minor = minor.parse().ok()?;
43 Some(Self { major, minor })
44 }
45 (Some(int), None, None) => {
46 let int: u64 = int.parse().ok()?;
47 Some(int.into())
48 }
49 _ => None,
50 }
51 })()
52 .with_context(|| ParseDeviceIdSnafu { string })
53 }
54}
55
56impl From<u64> for DeviceId {
57 fn from(num: u64) -> Self {
58 let dev = num as libc::dev_t;
60 Self {
61 major: libc::major(dev) as u32,
62 minor: libc::minor(dev) as u32,
63 }
64 }
65}
66
67impl DeviceId {
68 pub fn new(
69 major: u32,
70 minor: u32,
71 ) -> Self {
72 Self { major, minor }
73 }
74 pub fn of_path(path: &Path) -> Result<Self, Error> {
75 let md = fs::metadata(path).map_err(|e| Error::CantReadFileMetadata {
76 source: e,
77 path: path.to_path_buf(),
78 })?;
79 let dev_num = md.dev();
80 Ok(Self::from(dev_num))
81 }
82}
83
84#[test]
85fn test_from_str() {
86 assert_eq!(DeviceId::new(8, 16), DeviceId::from_str("8:16").unwrap());
87}