Skip to main content

libfuse_fs/util/
mod.rs

1pub mod bind_mount;
2pub mod mapping;
3pub mod open_options;
4
5use tracing::error;
6
7use std::{fmt::Display, path::PathBuf};
8
9use libc::stat64;
10use rfuse3::{FileType, Timestamp, raw::reply::FileAttr};
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Deserialize, Serialize, Clone, Default)]
14pub struct GPath {
15    pub path: Vec<String>,
16}
17
18impl GPath {
19    pub fn new() -> GPath {
20        GPath { path: Vec::new() }
21    }
22    pub fn push(&mut self, path: String) {
23        self.path.push(path);
24    }
25    pub fn pop(&mut self) -> Option<String> {
26        self.path.pop()
27    }
28    pub fn name(&self) -> String {
29        self.path.last().unwrap().clone()
30    }
31    pub fn part(&self, i: usize, j: usize) -> String {
32        self.path[i..j].join("/")
33    }
34}
35
36impl From<String> for GPath {
37    fn from(mut s: String) -> GPath {
38        if s.starts_with('/') {
39            s.remove(0);
40        }
41        GPath {
42            path: s.split('/').map(String::from).collect(),
43        }
44    }
45}
46
47impl From<GPath> for PathBuf {
48    fn from(val: GPath) -> Self {
49        let path_str = val.path.join("/");
50        PathBuf::from(path_str)
51    }
52}
53impl Display for GPath {
54    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
55        write!(f, "{}", self.path.join("/"))
56    }
57}
58
59pub fn convert_stat64_to_file_attr(stat: stat64) -> FileAttr {
60    FileAttr {
61        ino: stat.st_ino,
62        size: stat.st_size as u64,
63        blocks: stat.st_blocks as u64,
64        atime: Timestamp::new(stat.st_atime, stat.st_atime_nsec.try_into().unwrap()),
65        mtime: Timestamp::new(stat.st_mtime, stat.st_mtime_nsec.try_into().unwrap()),
66        ctime: Timestamp::new(stat.st_ctime, stat.st_ctime_nsec.try_into().unwrap()),
67        #[cfg(target_os = "macos")]
68        crtime: Timestamp::new(0, 0), // Set crtime to 0 for non-macOS platforms
69        kind: filetype_from_mode(stat.st_mode),
70        perm: (stat.st_mode & 0o7777) as u16,
71        nlink: stat.st_nlink as u32,
72        uid: stat.st_uid,
73        gid: stat.st_gid,
74        rdev: stat.st_rdev as u32,
75        #[cfg(target_os = "macos")]
76        flags: 0, // Set flags to 0 for non-macOS platforms
77        blksize: stat.st_blksize as u32,
78    }
79}
80
81pub fn filetype_from_mode(st_mode: u32) -> FileType {
82    let st_mode = st_mode & libc::S_IFMT;
83    match st_mode {
84        libc::S_IFIFO => FileType::NamedPipe,
85        libc::S_IFCHR => FileType::CharDevice,
86        libc::S_IFBLK => FileType::BlockDevice,
87        libc::S_IFDIR => FileType::Directory,
88        libc::S_IFREG => FileType::RegularFile,
89        libc::S_IFLNK => FileType::Symlink,
90        libc::S_IFSOCK => FileType::Socket,
91        _ => {
92            error!("wrong st mode : {st_mode}");
93            unreachable!();
94        }
95    }
96}
97#[cfg(test)]
98mod tests {
99    use super::GPath;
100
101    #[test]
102    fn test_from_string() {
103        let path = String::from("/release");
104        let gapth = GPath::from(path);
105        assert_eq!(gapth.to_string(), String::from("release"))
106    }
107}