1#[cfg(unix)]
30use {
31 core::cmp::Ordering,
32 std::{
33 fs::{self, Metadata},
34 io::Error,
35 os::unix::fs::PermissionsExt,
36 path::{Path, PathBuf},
37 },
38 crate::Result,
39};
40
41mod impls;
42
43#[cfg(test)]
44mod tests;
45
46#[cfg(unix)]
48#[doc(cfg(unix))]
49pub type RawPermission = u32;
50
51#[cfg(unix)]
57#[doc(cfg(unix))]
58#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, PartialOrd)]
59pub enum Permissions {
60
61 None = 0,
63
64 Read = 4,
66
67 Write = 2,
69
70 Execute = 1,
72
73 ReadWrite = Self::Read as isize | Self::Write as isize,
75
76 ReadExecute = Self::Read as isize | Self::Execute as isize,
78
79 WriteExecute = Self::Write as isize | Self::Execute as isize,
81
82 ReadWriteExecute = Self::Read as isize | Self::Write as isize | Self::Execute as isize,
84
85}
86
87#[cfg(unix)]
88#[doc(cfg(unix))]
89impl Ord for Permissions {
90
91 fn cmp(&self, other: &Self) -> Ordering {
92 (*self as RawPermission).cmp(&(*other as RawPermission))
93 }
94
95}
96
97#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, PartialOrd)]
114pub struct FilePermissions {
115
116 #[cfg(unix)]
117 user: Permissions,
118 #[cfg(unix)]
119 group: Permissions,
120 #[cfg(unix)]
121 others: Permissions,
122
123 #[cfg(not(unix))]
124 lock: (),
125
126}
127
128impl FilePermissions {
129
130 #[cfg(unix)]
132 #[doc(cfg(unix))]
133 pub const fn new(user: Permissions, group: Permissions, others: Permissions) -> Self {
134 Self {
135 user,
136 group,
137 others,
138 }
139 }
140
141 #[cfg(not(unix))]
143 #[doc(cfg(not(unix)))]
144 pub const fn new() -> Self {
145 Self {
146 lock: (),
147 }
148 }
149
150 #[cfg(unix)]
152 #[doc(cfg(unix))]
153 pub const fn user(&self) -> &Permissions {
154 &self.user
155 }
156
157 #[cfg(unix)]
159 #[doc(cfg(unix))]
160 pub const fn group(&self) -> &Permissions {
161 &self.group
162 }
163
164 #[cfg(unix)]
166 #[doc(cfg(unix))]
167 pub const fn others(&self) -> &Permissions {
168 &self.others
169 }
170
171 #[cfg(all(not(feature="async-std"), unix))]
173 #[doc(cfg(all(not(feature="async-std"), unix)))]
174 pub fn set<P>(&self, file: P) -> Result<()> where P: AsRef<Path> {
175 fs::set_permissions(file, self.into())
176 }
177
178 #[cfg(all(feature="async-std", unix))]
180 #[doc(cfg(all(feature="async-std", unix)))]
181 pub async fn set<P>(&self, file: P) -> Result<()> where P: AsRef<async_std::path::Path> {
182 async_std::fs::set_permissions(file, self.into()).await
183 }
184
185}
186
187#[cfg(unix)]
188#[doc(cfg(unix))]
189impl Ord for FilePermissions {
190
191 fn cmp(&self, other: &Self) -> Ordering {
192 RawPermission::from(self).cmp(&other.into())
193 }
194
195}
196
197#[cfg(unix)]
198macro_rules! impl_from_file_permissions_for_fs_permissions { ($($file_permissions: ty,)+) => {
199 $(
200 #[cfg(unix)]
201 #[doc(cfg(unix))]
202 impl From<$file_permissions> for fs::Permissions {
203
204 fn from(file_permissions: $file_permissions) -> Self {
205 Self::from_mode(file_permissions.into())
206 }
207
208 }
209 )+
210}}
211
212#[cfg(unix)]
213impl_from_file_permissions_for_fs_permissions! { &FilePermissions, FilePermissions, }
214
215#[cfg(unix)]
216#[doc(cfg(unix))]
217impl TryFrom<&fs::Permissions> for FilePermissions {
218
219 type Error = Error;
220
221 fn try_from(permissions: &fs::Permissions) -> Result<Self> {
222 let mode = permissions.mode();
223 Ok(Self::new(
224 Permissions::try_from(mode << 23 >> 29)?,
225 Permissions::try_from(mode << 26 >> 29)?,
226 Permissions::try_from(mode << 29 >> 29)?,
227 ))
228 }
229
230}
231
232#[cfg(unix)]
233#[doc(cfg(unix))]
234impl TryFrom<fs::Permissions> for FilePermissions {
235
236 type Error = Error;
237
238 fn try_from(permissions: fs::Permissions) -> Result<Self> {
239 Self::try_from(&permissions)
240 }
241
242}
243
244#[cfg(unix)]
245macro_rules! impl_try_from_metadata_for_file_permissions { ($($metadata: ty,)+) => {
246 $(
247 #[cfg(unix)]
248 #[doc(cfg(unix))]
249 impl TryFrom<$metadata> for FilePermissions {
250
251 type Error = Error;
252
253 fn try_from(metadata: $metadata) -> Result<Self> {
254 Self::try_from(&metadata.permissions())
255 }
256
257 }
258 )+
259}}
260
261#[cfg(unix)]
262impl_try_from_metadata_for_file_permissions! { &Metadata, Metadata, }
263
264#[cfg(unix)]
265macro_rules! impl_try_from_paths_for_file_permissions { ($($path: ty,)+) => {
266 $(
267 #[cfg(unix)]
268 #[doc(cfg(unix))]
269 impl TryFrom<$path> for FilePermissions {
270
271 type Error = Error;
272
273 fn try_from(path: $path) -> Result<Self> {
274 Self::try_from(&path.metadata()?.permissions())
275 }
276
277 }
278 )+
279}}
280
281#[cfg(unix)]
282impl_try_from_paths_for_file_permissions! { &Path, &PathBuf, PathBuf, }