Skip to main content

libblkid_rs/
partition.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::{ffi::CStr, marker::PhantomData};
6
7use uuid::Uuid;
8
9use crate::{
10    devno::BlkidDevno,
11    err::BlkidErr,
12    utils::{BlkidBytes, BlkidSectors},
13    Result,
14};
15
16/// A handle for working with partition tables.
17pub struct BlkidParttable<'a>(PhantomData<&'a ()>, libblkid_rs_sys::blkid_parttable);
18
19impl<'a> BlkidParttable<'a> {
20    /// Get the type of the partition table.
21    pub fn get_type(&self) -> Result<String> {
22        Ok(unsafe {
23            CStr::from_ptr(errno_ptr!(libblkid_rs_sys::blkid_parttable_get_type(
24                self.1
25            ))?)
26        }
27        .to_str()?
28        .to_string())
29    }
30
31    /// Get the ID of the partition table. Given that this could be a UUID or some
32    /// other form of identifier, the return value is a `String` to cover all cases.
33    pub fn get_id(&self) -> Result<String> {
34        Ok(
35            unsafe { CStr::from_ptr(errno_ptr!(libblkid_rs_sys::blkid_parttable_get_id(self.1))?) }
36                .to_str()?
37                .to_string(),
38        )
39    }
40
41    /// Get the offset of the partition table in bytes.
42    pub fn get_offset(&self) -> Result<BlkidBytes> {
43        Ok(BlkidBytes::new(errno_with_ret!(unsafe {
44            libblkid_rs_sys::blkid_parttable_get_offset(self.1)
45        })?))
46    }
47
48    /// Get the parent partition in the case of nested partition tables.
49    pub fn get_parent(&self) -> Option<BlkidPartition<'a>> {
50        option_ptr!(unsafe { libblkid_rs_sys::blkid_parttable_get_parent(self.1) })
51            .map(|p| BlkidPartition(PhantomData, p))
52    }
53}
54
55/// A handle for working with a probed partition.
56pub struct BlkidPartition<'a>(PhantomData<&'a ()>, libblkid_rs_sys::blkid_partition);
57
58impl<'a> BlkidPartition<'a> {
59    /// Get the partition table for the given partition.
60    pub fn get_table(&self) -> Result<BlkidParttable<'a>> {
61        Ok(BlkidParttable(
62            PhantomData,
63            errno_ptr!(unsafe { libblkid_rs_sys::blkid_partition_get_table(self.1) })?,
64        ))
65    }
66
67    /// Get the partition name or `None` if it can't be represented.
68    pub fn get_name(&self) -> Result<Option<String>> {
69        let char_ptr =
70            match option_ptr!(unsafe { libblkid_rs_sys::blkid_partition_get_name(self.1) }) {
71                Some(ptr) => ptr,
72                None => return Ok(None),
73            };
74        unsafe { CStr::from_ptr(char_ptr) }
75            .to_str()
76            .map(|s| Some(s.to_string()))
77            .map_err(BlkidErr::UTF8)
78    }
79
80    /// Get the partition UUID or `None` if the partition table doesn't support it.
81    pub fn get_uuid(&self) -> Result<Option<Uuid>> {
82        let char_ptr =
83            match option_ptr!(unsafe { libblkid_rs_sys::blkid_partition_get_uuid(self.1) }) {
84                Some(ptr) => ptr,
85                None => return Ok(None),
86            };
87        match unsafe { CStr::from_ptr(char_ptr) }.to_str() {
88            Ok(s) => Ok(Some(Uuid::parse_str(s).map_err(BlkidErr::Uuid)?)),
89            Err(e) => Err(BlkidErr::UTF8(e)),
90        }
91    }
92
93    /// Get the partition number.
94    pub fn get_partno(&self) -> Result<libc::c_uint> {
95        errno_with_ret!(unsafe { libblkid_rs_sys::blkid_partition_get_partno(self.1) })
96            .map(|i| i as libc::c_uint)
97    }
98
99    /// Get the start of the partition in units of sectors.
100    pub fn get_start(&self) -> BlkidSectors {
101        BlkidSectors::new(unsafe { libblkid_rs_sys::blkid_partition_get_start(self.1) })
102    }
103
104    /// Get the size of the partition in units of sectors.
105    pub fn get_size(&self) -> BlkidSectors {
106        BlkidSectors::new(unsafe { libblkid_rs_sys::blkid_partition_get_size(self.1) })
107    }
108
109    /// Get the numeric partition type. Use `get_type_string` for the `String`
110    /// representation.
111    pub fn get_type(&self) -> libc::c_int {
112        unsafe { libblkid_rs_sys::blkid_partition_get_type(self.1) }
113    }
114
115    /// Get the string representation of the partition type.
116    pub fn get_type_string(&self) -> Result<String> {
117        Ok(unsafe {
118            CStr::from_ptr(errno_ptr!(
119                libblkid_rs_sys::blkid_partition_get_type_string(self.1)
120            )?)
121        }
122        .to_str()?
123        .to_string())
124    }
125
126    /// Get the flags for the given partition.
127    ///
128    /// This method is not typed as the documentation does not specify which
129    /// constants are used as flags.
130    pub fn get_flags(&self) -> libc::c_ulonglong {
131        unsafe { libblkid_rs_sys::blkid_partition_get_flags(self.1) }
132    }
133
134    /// Check whether the given partition is logical.
135    pub fn is_logical(&self) -> bool {
136        (unsafe { libblkid_rs_sys::blkid_partition_is_logical(self.1) }) != 0
137    }
138
139    /// Check whether the given partition is an extended partition.
140    pub fn is_extended(&self) -> bool {
141        (unsafe { libblkid_rs_sys::blkid_partition_is_extended(self.1) }) != 0
142    }
143
144    /// Check whether the given partition is a primary partition.
145    pub fn is_primary(&self) -> bool {
146        (unsafe { libblkid_rs_sys::blkid_partition_is_primary(self.1) }) != 0
147    }
148}
149
150/// A handle for traversing a list of partitions.
151pub struct BlkidPartlist<'a>(PhantomData<&'a ()>, libblkid_rs_sys::blkid_partlist);
152
153impl<'a> BlkidPartlist<'a> {
154    pub(crate) fn new(partlist: libblkid_rs_sys::blkid_partlist) -> BlkidPartlist<'a> {
155        BlkidPartlist(PhantomData, partlist)
156    }
157
158    /// Get the number of partitions in the list.
159    pub fn number_of_partitions(&mut self) -> Result<libc::c_int> {
160        errno_with_ret!(unsafe { libblkid_rs_sys::blkid_partlist_numof_partitions(self.1) })
161    }
162
163    /// Get the partition table for a list of partitions.
164    pub fn get_table(&mut self) -> Result<BlkidParttable<'a>> {
165        Ok(BlkidParttable(
166            PhantomData,
167            errno_ptr!(unsafe { libblkid_rs_sys::blkid_partlist_get_table(self.1) })?,
168        ))
169    }
170
171    /// Get a partition at the given index of the list.
172    pub fn get_partition(&mut self, index: libc::c_int) -> Result<BlkidPartition<'a>> {
173        Ok(BlkidPartition(
174            PhantomData,
175            errno_ptr!(unsafe { libblkid_rs_sys::blkid_partlist_get_partition(self.1, index) })?,
176        ))
177    }
178
179    /// Get a partition by the number listed in the partition table. Correctly
180    /// handles "out-of-order" partition tables.
181    pub fn get_partition_by_partno(&mut self, num: libc::c_int) -> Result<BlkidPartition<'a>> {
182        Ok(BlkidPartition(
183            PhantomData,
184            errno_ptr!(unsafe {
185                libblkid_rs_sys::blkid_partlist_get_partition_by_partno(self.1, num)
186            })?,
187        ))
188    }
189
190    /// Get a partition using the device number of a partition.
191    pub fn get_partition_by_devno(&mut self, dev: &BlkidDevno) -> Result<BlkidPartition<'a>> {
192        Ok(BlkidPartition(
193            PhantomData,
194            errno_ptr!(unsafe {
195                libblkid_rs_sys::blkid_partlist_devno_to_partition(self.1, dev.as_dev_t())
196            })?,
197        ))
198    }
199}