chj_rustbin/io/
unix_fs.rs1use enumn::N;
6use nix::sys::stat::FileStat;
7use std::ffi::CStr;
8
9#[derive(N, Eq, PartialEq, Debug)]
10#[repr(u8)]
11pub enum FileType {
12 Pipe = 1,
14 CharDevice = 2,
15 Dir = 4,
16 BlockDevice = 6,
17 File = 8,
18 Link = 10,
19 Socket = 12,
20}
21
22pub trait EasyFileStat {
23 fn filetype(&self) -> FileType;
24}
25
26impl EasyFileStat for FileStat {
27 fn filetype(&self) -> FileType {
28 FileType::n(stat_filetype(self))
29 .expect("OS using one of the known constants")
30 }
31}
32
33fn stat_filetype(st: &FileStat) -> u8 {
34 ((st.st_mode & 0o0170000) >> 12) as u8
35}
36
37pub fn path_is_type(
41 path: &CStr,
42 ftypes: &[FileType],
43 follow_links: bool,
44) -> bool {
45 let statfunction: fn(&CStr) -> _ = if follow_links {
46 nix::sys::stat::stat
47 } else {
48 nix::sys::stat::lstat
49 };
50 match statfunction(path) {
51 Ok(m) => ftypes.iter().any(|ftype| m.filetype() == *ftype),
52 Err(_) => false,
53 }
54}
55
56pub fn path_is_file(path: &CStr) -> bool {
57 path_is_type(path, &[FileType::File], false)
58}
59pub fn path_is_dir(path: &CStr) -> bool {
60 path_is_type(path, &[FileType::Dir], false)
61}
62pub fn path_is_link(path: &CStr) -> bool {
63 path_is_type(path, &[FileType::Link], false)
64}
65pub fn path_is_blockdevice(path: &CStr) -> bool {
66 path_is_type(path, &[FileType::BlockDevice], false)
67}
68pub fn path_is_pipe(path: &CStr) -> bool {
69 path_is_type(path, &[FileType::Pipe], false)
70}
71pub fn path_is_socket(path: &CStr) -> bool {
72 path_is_type(path, &[FileType::Socket], false)
73}
74pub fn path_is_chardevice(path: &CStr) -> bool {
75 path_is_type(path, &[FileType::CharDevice], false)
76}
77
78pub fn path_is_normal_file(path: &CStr) -> bool {
79 path_is_type(path, &[FileType::File, FileType::Dir], true)
80}
81
82#[cfg(test)]
83mod tests {
84 use std::ffi::CString;
85
86 use super::*;
87
88 #[test]
89 fn t_filetype() {
90 fn t(f: fn(&CStr) -> bool, s: &str, expected: bool) {
91 assert_eq!(f(&CString::new(s).unwrap()), expected);
92 }
93 t(path_is_dir, ".", true);
94 t(path_is_file, ".", false);
95 t(path_is_dir, "8hbrr2kz8kmztb4dqh4", false);
97 t(path_is_file, "8hbrr2kz8kmztb4dqh4", false);
98 t(path_is_file, "/etc/fstab", true);
100 t(path_is_chardevice, "/dev/null", true);
101 t(path_is_chardevice, "/dev/loop0", false);
102 t(path_is_blockdevice, "/dev/sda", true);
103 t(path_is_normal_file, "/dev/sda", false);
104 t(path_is_normal_file, "8hbrr2kz8kmztb4dqh4", false);
105 t(path_is_normal_file, "/etc/fstab", true);
106 t(path_is_link, "/etc/localtime", true);
107 t(path_is_normal_file, "/etc/localtime", true);
108 }
109}