1use std::{
6 ffi::{CStr, CString},
7 path::Path,
8 ptr,
9};
10
11use either::Either;
12
13use libblkid_rs_sys::blkid_cache;
14use libc::{c_void, free};
15
16use crate::{
17 consts::BlkidDevFlags,
18 dev::{BlkidDev, BlkidDevIter},
19 err::{BlkidErr, Result},
20};
21
22pub struct BlkidCache(blkid_cache, bool);
24
25impl BlkidCache {
26 pub(crate) fn as_mut_ptr(&mut self) -> *mut blkid_cache {
27 &mut self.0 as *mut _
28 }
29
30 pub fn put_cache(&mut self) {
32 unsafe { libblkid_rs_sys::blkid_put_cache(self.0) };
33 self.1 = true;
34 }
35
36 pub fn get_cache(filename: Option<&Path>) -> Result<Self> {
40 let mut cache = ptr::null_mut();
41 let filename_cstring = match filename {
42 Some(fname) => Some(CString::new(fname.to_str().ok_or(BlkidErr::InvalidConv)?)?),
43 None => None,
44 };
45 errno!(unsafe {
46 libblkid_rs_sys::blkid_get_cache(
47 &mut cache as *mut _,
48 filename_cstring
49 .as_ref()
50 .map(|s| s.as_ptr())
51 .unwrap_or(ptr::null_mut()),
52 )
53 })?;
54 Ok(BlkidCache(cache, false))
55 }
56
57 pub fn gc_cache(&mut self) {
59 unsafe { libblkid_rs_sys::blkid_gc_cache(self.0) }
60 }
61
62 pub fn iter(&self) -> BlkidDevIter {
64 BlkidDevIter::new(unsafe { libblkid_rs_sys::blkid_dev_iterate_begin(self.0) })
65 }
66
67 pub fn probe_all(&mut self) -> Result<()> {
69 errno!(unsafe { libblkid_rs_sys::blkid_probe_all(self.0) })
70 }
71
72 pub fn probe_all_new(&mut self) -> Result<()> {
74 errno!(unsafe { libblkid_rs_sys::blkid_probe_all_new(self.0) })
75 }
76
77 pub fn probe_all_removable(&mut self) -> Result<()> {
79 errno!(unsafe { libblkid_rs_sys::blkid_probe_all_removable(self.0) })
80 }
81
82 pub fn get_dev(&self, devname: &Path, flags: BlkidDevFlags) -> Result<BlkidDev> {
86 let devname_cstring =
87 CString::new(devname.to_str().ok_or(BlkidErr::InvalidConv)?.as_bytes())?;
88 Ok(BlkidDev::new(unsafe {
89 libblkid_rs_sys::blkid_get_dev(self.0, devname_cstring.as_ptr(), flags.into())
90 }))
91 }
92
93 pub fn get_tag_value(&self, tag_name: &str, devname: &Path) -> Result<String> {
95 let tag_name_cstring = CString::new(tag_name.as_bytes())?;
96 let devname_cstring =
97 CString::new(devname.to_str().ok_or(BlkidErr::InvalidConv)?.as_bytes())?;
98 let ptr = errno_ptr!(unsafe {
99 libblkid_rs_sys::blkid_get_tag_value(
100 self.0,
101 tag_name_cstring.as_ptr(),
102 devname_cstring.as_ptr(),
103 )
104 })?;
105 let string = unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string();
106 unsafe { libc::free(ptr as *mut libc::c_void) };
107 Ok(string)
108 }
109
110 pub fn get_devname(&self, token_or_pair: Either<&str, (&str, &str)>) -> Result<String> {
112 let (name, value) = match token_or_pair {
113 Either::Left(token) => {
114 if !token.contains('=') {
115 return Err(BlkidErr::Other(
116 "Token input requires the format NAME=value".to_string(),
117 ));
118 }
119 let mut split = token.split('=');
120 match (split.next(), split.next()) {
121 (Some(name), Some(value)) => (name, value),
122 (_, _) => {
123 return Err(BlkidErr::Other(
124 "Token input requires the format NAME=value".to_string(),
125 ));
126 }
127 }
128 }
129 Either::Right((name, value)) => (name, value),
130 };
131 let name_cstring = CString::new(name.as_bytes())?;
132 let value_cstring = CString::new(value.as_bytes())?;
133 let ptr = errno_ptr!(unsafe {
134 libblkid_rs_sys::blkid_get_devname(
135 self.0,
136 name_cstring.as_ptr(),
137 value_cstring.as_ptr(),
138 )
139 })?;
140 let string = unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string();
141 unsafe { libc::free(ptr as *mut libc::c_void) };
142 Ok(string)
143 }
144
145 pub fn find_dev_with_tag(&self, type_: &str, value: &str) -> Result<BlkidDev> {
147 let type_cstring = CString::new(type_)?;
148 let value_cstring = CString::new(value)?;
149 let ptr = errno_ptr!(unsafe {
150 libblkid_rs_sys::blkid_find_dev_with_tag(
151 self.0,
152 type_cstring.as_ptr(),
153 value_cstring.as_ptr(),
154 )
155 })?;
156 Ok(BlkidDev::new(ptr))
157 }
158
159 pub fn verify(&mut self, dev: BlkidDev) -> Option<BlkidDev> {
161 let ptr = unsafe { libblkid_rs_sys::blkid_verify(self.0, dev.as_ptr()) };
162 if ptr.is_null() {
163 None
164 } else {
165 Some(BlkidDev::new(ptr))
166 }
167 }
168}
169
170impl Drop for BlkidCache {
171 fn drop(&mut self) {
172 if !self.1 {
173 unsafe { free(self.0 as *mut c_void) }
174 }
175 }
176}