Skip to main content

xen/store/
mod.rs

1mod handle;
2use std::{
3    ffi::{CStr, CString, c_char, c_void},
4    rc::Rc,
5};
6
7use xen_sys::{XBT_NULL, xs_directory, xs_read};
8
9pub use self::handle::XenStoreHandle;
10use crate::{XenDomainId, XenError};
11
12#[derive(Debug, Clone)]
13pub struct XenStore {
14    pub(crate) handle: Rc<XenStoreHandle>,
15}
16
17impl XenStore {
18    pub fn new() -> Result<Self, XenError> {
19        Ok(Self {
20            handle: Rc::new(XenStoreHandle::new()?),
21        })
22    }
23
24    pub fn domain_id_from_name(&self, name: &str) -> Result<Option<XenDomainId>, XenError> {
25        for domain in self.directory("/local/domain")? {
26            let domain_name = self.read(&format!("/local/domain/{domain}/name"))?;
27            if domain_name == name {
28                match domain.parse() {
29                    Ok(domain) => return Ok(Some(XenDomainId(domain))),
30                    Err(_) => return Err(XenError::Other("Failed to parse domain id")),
31                }
32            }
33        }
34
35        Ok(None)
36    }
37
38    pub fn directory(&self, path: &str) -> Result<Vec<String>, XenError> {
39        let path = CString::new(path).unwrap();
40        let mut num = 0;
41        let result = unsafe { xs_directory(self.handle.0, XBT_NULL, path.as_ptr(), &mut num) };
42
43        if result.is_null() {
44            return Err(XenError::Other("Failed to read xen store directory"));
45        }
46
47        let mut entries = Vec::with_capacity(num as usize);
48        for i in 0..num {
49            let entry = unsafe { CStr::from_ptr(*result.offset(i as isize)) };
50            entries.push(entry.to_string_lossy().into());
51        }
52
53        unsafe {
54            libc::free(result as *mut c_void);
55        }
56
57        Ok(entries)
58    }
59
60    pub fn read(&self, path: &str) -> Result<String, XenError> {
61        let mut len = 0;
62        let path = CString::new(path).unwrap();
63        let result = unsafe { xs_read(self.handle.0, XBT_NULL, path.as_ptr(), &mut len) };
64        if result.is_null() {
65            return Err(XenError::Other("Failed to read xen store"));
66        }
67
68        let value = unsafe { CStr::from_ptr(result as *const c_char) };
69        let value = value.to_string_lossy().into_owned();
70
71        unsafe {
72            libc::free(result);
73        }
74
75        Ok(value)
76    }
77}