1use crate::error::{MyError, MyResult};
2use crate::fs::entry::Entry;
3use crate::fs::flags::FileFlags;
4use crate::fs::system::{System, EXEC_MASK};
5use std::collections::HashSet;
6
7#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
8pub enum ExecKind {
9 None,
10 User,
11 Other,
12}
13
14#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
15pub enum FileKind {
16 File(ExecKind),
17 Dir,
18 Link(bool), Other,
20}
21
22impl FileKind {
23 fn from_char(ch: char) -> Option<Vec<Self>> {
24 match ch {
25 'f' => Some(vec![
26 Self::File(ExecKind::None),
27 Self::File(ExecKind::User),
28 Self::File(ExecKind::Other),
29 ]),
30 'e' => Some(vec![
31 Self::File(ExecKind::User),
32 Self::File(ExecKind::Other),
33 ]),
34 'd' => Some(vec![
35 Self::Dir,
36 ]),
37 'l' => Some(vec![
38 Self::Link(false),
39 Self::Link(true),
40 ]),
41 _ => None,
42 }
43 }
44
45 pub fn from_entry<S: System>(system: &S, entry: &dyn Entry) -> Self {
46 match entry.file_flags() {
47 FileFlags::File => Self::parse_file(system, entry),
48 FileFlags::Dir => Self::Dir,
49 FileFlags::Link => Self::Link(true),
50 FileFlags::Other => Self::Other,
51 }
52 }
53
54 #[cfg(unix)]
55 fn parse_file<S: System>(system: &S, entry: &dyn Entry) -> Self {
56 if (entry.file_mode() & system.get_mask(entry.owner_uid(), entry.owner_gid())) != 0 {
57 Self::File(ExecKind::User)
58 } else if (entry.file_mode() & EXEC_MASK) != 0 {
59 Self::File(ExecKind::Other)
60 } else {
61 Self::File(ExecKind::None)
62 }
63 }
64
65 #[cfg(not(unix))]
66 fn parse_file<S: System>(_system: &S, entry: &dyn Entry) -> Self {
67 if (entry.file_mode() & EXEC_MASK) != 0 {
68 Self::File(ExecKind::User)
69 } else {
70 Self::File(ExecKind::None)
71 }
72 }
73
74 pub fn dir_offset(&self) -> usize {
75 if *self == Self::Dir { 1 } else { 0 }
76 }
77}
78
79#[derive(Clone)]
80pub struct FileSet {
81 pub inner: HashSet<FileKind>,
82}
83
84impl FileSet {
85 pub fn from_str(value: &str) -> MyResult<Self> {
86 let mut inner = HashSet::new();
87 for ch in value.chars() {
88 if let Some(items) = FileKind::from_char(ch) {
89 inner.extend(items);
90 } else {
91 return Err(MyError::create_clap("type", ch));
92 }
93 }
94 let results = Self { inner };
95 Ok(results)
96 }
97}