1 // Stolen from https://github.com/Peltoche/lsd/blob/master/src/meta/permissions.rs
2 
3 use serde::{Deserialize, Serialize};
4 use std::fs::Metadata;
5 
6 #[derive(
7     Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Hash, Default,
8 )]
9 pub struct Permissions {
10     pub user_read: bool,
11     pub user_write: bool,
12     pub user_execute: bool,
13 
14     pub group_read: bool,
15     pub group_write: bool,
16     pub group_execute: bool,
17 
18     pub other_read: bool,
19     pub other_write: bool,
20     pub other_execute: bool,
21 
22     pub sticky: bool,
23     pub setgid: bool,
24     pub setuid: bool,
25 }
26 
27 impl<'a> From<&'a Metadata> for Permissions {
28     #[cfg(unix)]
from(meta: &Metadata) -> Self29     fn from(meta: &Metadata) -> Self {
30         use std::os::unix::fs::PermissionsExt;
31 
32         let bits = meta.permissions().mode();
33         let has_bit = |bit| bits & bit == bit;
34 
35         Self {
36             user_read: has_bit(modes::USER_READ),
37             user_write: has_bit(modes::USER_WRITE),
38             user_execute: has_bit(modes::USER_EXECUTE),
39 
40             group_read: has_bit(modes::GROUP_READ),
41             group_write: has_bit(modes::GROUP_WRITE),
42             group_execute: has_bit(modes::GROUP_EXECUTE),
43 
44             other_read: has_bit(modes::OTHER_READ),
45             other_write: has_bit(modes::OTHER_WRITE),
46             other_execute: has_bit(modes::OTHER_EXECUTE),
47 
48             sticky: has_bit(modes::STICKY),
49             setgid: has_bit(modes::SETGID),
50             setuid: has_bit(modes::SETUID),
51         }
52     }
53 
54     #[cfg(windows)]
from(_: &Metadata) -> Self55     fn from(_: &Metadata) -> Self {
56         panic!("Cannot get permissions from metadata on Windows")
57     }
58 }
59 
60 // More readable aliases for the permission bits exposed by libc.
61 #[allow(trivial_numeric_casts)]
62 #[cfg(unix)]
63 mod modes {
64     pub type Mode = u32;
65     // The `libc::mode_t` type’s actual type varies, but the value returned
66     // from `metadata.permissions().mode()` is always `u32`.
67 
68     pub const USER_READ: Mode = libc::S_IRUSR as Mode;
69     pub const USER_WRITE: Mode = libc::S_IWUSR as Mode;
70     pub const USER_EXECUTE: Mode = libc::S_IXUSR as Mode;
71 
72     pub const GROUP_READ: Mode = libc::S_IRGRP as Mode;
73     pub const GROUP_WRITE: Mode = libc::S_IWGRP as Mode;
74     pub const GROUP_EXECUTE: Mode = libc::S_IXGRP as Mode;
75 
76     pub const OTHER_READ: Mode = libc::S_IROTH as Mode;
77     pub const OTHER_WRITE: Mode = libc::S_IWOTH as Mode;
78     pub const OTHER_EXECUTE: Mode = libc::S_IXOTH as Mode;
79 
80     pub const STICKY: Mode = libc::S_ISVTX as Mode;
81     pub const SETGID: Mode = libc::S_ISGID as Mode;
82     pub const SETUID: Mode = libc::S_ISUID as Mode;
83 }
84