udevrs/
file.rs

1use std::{ffi, io};
2
3use crate::{Error, Result};
4
5/// Represents an FFI type from `fcntl.h` for a `file_handle`.
6#[repr(C)]
7#[allow(non_snake_case)]
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct file_handle {
10    handle_bytes: u8,
11    handle_type: i32,
12    f_handle: *mut u8,
13}
14
15impl file_handle {
16    /// Creates a new [file_handle].
17    pub const fn new() -> Self {
18        Self {
19            handle_bytes: 0,
20            handle_type: 0,
21            f_handle: std::ptr::null_mut(),
22        }
23    }
24
25    pub fn as_ptr(&self) -> *const Self {
26        self as *const _
27    }
28
29    pub fn as_void_ptr(&self) -> *const ffi::c_void {
30        self.as_ptr() as *const _
31    }
32
33    pub fn as_ptr_mut(&mut self) -> *mut Self {
34        self as *mut _
35    }
36
37    pub fn as_void_ptr_mut(&mut self) -> *mut ffi::c_void {
38        self.as_ptr_mut() as *mut _
39    }
40}
41
42impl Default for file_handle {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48/// Wrapper around a syscall that returns an opaque handle that corresponds to a specified file.
49pub fn name_to_handle_at(
50    dir_fd: i32,
51    path: &str,
52    handle: &mut file_handle,
53    mount_id: &mut i32,
54    flags: i32,
55) -> Result<()> {
56    let path_str = ffi::CString::new(path)?;
57
58    // SAFETY: parameters are initialized properly, and pointers reference valid memory.
59    let ret = unsafe {
60        libc::syscall(
61            libc::SYS_name_to_handle_at,
62            dir_fd,
63            path_str.as_ptr(),
64            handle.as_void_ptr_mut(),
65            mount_id as *mut i32,
66            flags,
67        )
68    };
69
70    if ret == 0 {
71        Ok(())
72    } else {
73        let errno = io::Error::last_os_error();
74        let errmsg = format!("error calling `name_to_handle_at`, ret: {ret}, errno: {errno}");
75
76        log::warn!("{errmsg}");
77
78        Err(Error::io(errno.kind(), errmsg))
79    }
80}