1use std::{sync::Arc, time::Duration};
2
3use anyhow::{anyhow, Result};
4use krataloopdev::{LoopControl, LoopDevice};
5use log::debug;
6use tokio::time::sleep;
7use xenclient::BlockDeviceRef;
8
9#[derive(Clone)]
10pub struct AutoLoop {
11 control: Arc<LoopControl>,
12}
13
14impl AutoLoop {
15 pub fn new(control: LoopControl) -> AutoLoop {
16 AutoLoop {
17 control: Arc::new(control),
18 }
19 }
20
21 pub fn loopify(&self, file: &str) -> Result<BlockDeviceRef> {
22 debug!("creating loop for file {}", file);
23 let device = self.control.next_free()?;
24 device.with().read_only(true).attach(file)?;
25 let path = device
26 .path()
27 .ok_or(anyhow!("unable to get loop device path"))?
28 .to_str()
29 .ok_or(anyhow!("unable to convert loop device path to string",))?
30 .to_string();
31 let major = device.major()?;
32 let minor = device.minor()?;
33 Ok(BlockDeviceRef { path, major, minor })
34 }
35
36 pub async fn unloop(&self, device: &str) -> Result<()> {
37 let device = LoopDevice::open(device)?;
38 device.detach()?;
39 sleep(Duration::from_millis(200)).await;
40 Ok(())
41 }
42}