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), 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, 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}