1mod ioctls;
16
17use anyhow::*;
18use uuid::Uuid;
19
20use std::{
21 ffi::CString,
22 fs,
23 os::{fd::AsRawFd, unix::ffi::OsStrExt},
24 path,
25};
26
27pub fn query_uuid(path: impl AsRef<path::Path>) -> Result<Uuid> {
28 let mut query_result: ioctls::QueryUuidPayload = Default::default();
29 unsafe { ioctls::query_uuid(fs::File::open(path)?.as_raw_fd(), &mut query_result)? };
30 Ok(Uuid::from_bytes(query_result.uuid))
31}
32
33enum SubvolOperation {
34 Create,
35 Destroy,
36 }
38
39fn do_subvolume_ioctl(path: impl AsRef<path::Path>, operation: SubvolOperation) -> Result<()> {
40 let path = std::path::absolute(path.as_ref())?;
41
42 let parent = path.parent().context("Path has no parent.")?;
43 let parent_handle = fs::File::open(parent)?;
44 let dst = CString::new(path.as_os_str().as_bytes())?;
45
46 let payload = ioctls::SubvolumePayload {
47 mode: 0o777,
48 dst_ptr: dst.as_ptr() as u64,
49 ..Default::default()
50 };
51
52 let parent_fd = parent_handle.as_raw_fd();
53
54 match operation {
55 SubvolOperation::Create => unsafe {
56 ioctls::subvolume_create(parent_fd, &payload)?;
57 },
58 SubvolOperation::Destroy => unsafe {
59 ioctls::subvolume_destroy(parent_fd, &payload)?;
60 },
61 }
62
63 Ok(())
64}
65
66pub fn create_subvolume(path: impl AsRef<path::Path>) -> Result<()> {
67 do_subvolume_ioctl(path, SubvolOperation::Create)
68}
69
70pub fn destroy_subvolume(path: impl AsRef<path::Path>) -> Result<()> {
71 do_subvolume_ioctl(path, SubvolOperation::Destroy)
72}