file_system/fundamentals/
permission.rs

1use core::fmt;
2
3use crate::Kind;
4
5/// Represents the permissions of a file or directory.
6///
7/// The permissions are divided into three groups: user, group, and others.
8/// Each group has three permissions: read, write, and execute.
9///
10/// # Examples
11///
12/// ```rust
13/// use file_system::{Permissions_type, Permission_type, Special_type};
14///
15/// let user = Permission_type::new(true, false, false); // Read only
16/// let group = Permission_type::new(false, true, false); // Write only
17/// let others = Permission_type::new(false, false, true); // Execute only
18/// let special = Special_type::new(true, false, true); // Sticky and set user identifier
19///
20/// let permissions = Permissions_type::new(user, group, others, special);
21///
22/// assert_eq!(permissions.get_user(), user);
23/// assert_eq!(permissions.get_group(), group);
24/// assert_eq!(permissions.get_others(), others);
25/// assert_eq!(permissions.get_special(), special);
26/// ```
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28#[repr(transparent)]
29pub struct Permissions(u16);
30
31impl fmt::Display for Permissions {
32    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33        let user = self.get_user();
34        let group = self.get_group();
35        let others = self.get_others();
36
37        write!(f, "{user}{group}{others}")
38    }
39}
40
41impl Permissions {
42    pub const NONE: Self = Self::new(
43        Permission::NONE,
44        Permission::NONE,
45        Permission::NONE,
46        Special::NONE,
47    );
48    pub const ALL_FULL: Self = Self::new(
49        Permission::FULL,
50        Permission::FULL,
51        Permission::FULL,
52        Special::NONE,
53    );
54    pub const ALL_READ_WRITE: Self = Self::new(
55        Permission::READ_WRITE,
56        Permission::READ_WRITE,
57        Permission::READ_WRITE,
58        Special::NONE,
59    );
60    pub const USER_FULL: Self = Self::new(
61        Permission::FULL,
62        Permission::NONE,
63        Permission::NONE,
64        Special::NONE,
65    );
66    pub const USER_READ_WRITE: Self = Self::new(
67        Permission::READ_WRITE,
68        Permission::NONE,
69        Permission::NONE,
70        Special::NONE,
71    );
72    pub const EXECUTABLE: Self = Self::new(
73        Permission::FULL,
74        Permission::READ_EXECUTE,
75        Permission::READ_EXECUTE,
76        Special::NONE,
77    );
78
79    /// Creates a new permission.
80    pub const fn new(
81        user: Permission,
82        group: Permission,
83        others: Permission,
84        special: Special,
85    ) -> Self {
86        Self(
87            (special.to_unix() as u16) << 9
88                | (user.to_unix() as u16) << 6
89                | (group.to_unix() as u16) << 3
90                | others.to_unix() as u16,
91        )
92    }
93
94    /// Creates a new permission with read access for user. No access for group and others.
95    pub const fn new_default(r#type: Kind) -> Self {
96        match r#type {
97            Kind::Directory => Self::new(
98                Permission::FULL,
99                Permission::READ_EXECUTE,
100                Permission::READ_EXECUTE,
101                Special::NONE,
102            ),
103            Kind::File => Self::new(
104                Permission::READ_WRITE,
105                Permission::READ_ONLY,
106                Permission::READ_ONLY,
107                Special::NONE,
108            ),
109            Kind::Pipe => Self::new(
110                Permission::READ_WRITE,
111                Permission::NONE,
112                Permission::NONE,
113                Special::NONE,
114            ),
115            Kind::BlockDevice => Self::new(
116                Permission::FULL,
117                Permission::READ_WRITE,
118                Permission::READ_WRITE,
119                Special::NONE,
120            ),
121            Kind::CharacterDevice => Self::new(
122                Permission::READ_WRITE,
123                Permission::READ_WRITE,
124                Permission::NONE,
125                Special::NONE,
126            ),
127            Kind::Socket => Self::ALL_READ_WRITE,
128            Kind::SymbolicLink => Self::ALL_FULL,
129        }
130    }
131
132    /// Sets the permission for the user.
133    pub fn set_user(mut self, user: Permission) -> Self {
134        self.0 = (self.0 & 0o7077) | (user.to_unix() as u16) << 6;
135        self
136    }
137
138    /// Sets the permission for the group.
139    pub fn set_group(mut self, group: Permission) -> Self {
140        self.0 = (self.0 & 0o7707) | (group.to_unix() as u16) << 3;
141        self
142    }
143
144    /// Sets the permission for others.
145    pub fn set_others(mut self, others: Permission) -> Self {
146        self.0 = (self.0 & 0o7770) | others.to_unix() as u16;
147        self
148    }
149
150    /// Sets the special permissions.
151    pub fn set_special(mut self, special: Special) -> Self {
152        self.0 = (self.0 & 0o0777) | (special.to_unix() as u16) << 9;
153        self
154    }
155
156    /// Gets the permission for the user.
157    pub fn get_user(&self) -> Permission {
158        Permission::from_unix(((self.0 >> 6) & 0b111) as u8).unwrap()
159    }
160
161    /// Gets the permission for the group.
162    pub fn get_group(&self) -> Permission {
163        Permission::from_unix(((self.0 >> 3) & 0b111) as u8).unwrap()
164    }
165
166    /// Gets the permission for others.
167    pub fn get_others(&self) -> Permission {
168        Permission::from_unix((self.0 & 0b111) as u8).unwrap()
169    }
170
171    /// Gets the special permissions.
172    pub fn get_special(&self) -> Special {
173        Special::from_unix((self.0 >> 9) as u8).unwrap()
174    }
175
176    /// Converts the permission to a Unix permission.
177    pub const fn from_octal(unix: u16) -> Option<Self> {
178        if unix > 0o777 {
179            return None;
180        }
181
182        Some(Self(unix))
183    }
184
185    /// Converts the permission to a Unix permission.
186    pub const fn as_u16(&self) -> u16 {
187        self.0
188    }
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192#[repr(transparent)]
193pub struct Special(u8);
194
195impl fmt::Display for Special {
196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197        let sticky = if self.get_sticky() { "t" } else { "-" };
198        let set_gid = if self.get_set_group_identifier() {
199            "u"
200        } else {
201            "-"
202        };
203        let set_uid = if self.get_set_user_identifier() {
204            "g"
205        } else {
206            "-"
207        };
208
209        write!(f, "{sticky}{set_gid}{set_uid}")
210    }
211}
212
213impl Special {
214    pub const NONE: Self = Self(0);
215    pub const STICKY: Self = Self(1);
216    pub const SET_USER_IDENTIFIER: Self = Self(2);
217    pub const SET_GROUP_IDENTIFIER: Self = Self(4);
218
219    pub fn new(sticky: bool, set_gid: bool, set_uid: bool) -> Self {
220        Self((sticky as u8) | (set_gid as u8) << 1 | (set_uid as u8) << 2)
221    }
222
223    pub fn set_sticky(mut self, sticky: bool) -> Self {
224        self.0 = (self.0 & 0b110) | sticky as u8;
225        self
226    }
227
228    pub fn set_set_group_identifier(mut self, set_gid: bool) -> Self {
229        self.0 = (self.0 & 0b101) | (set_gid as u8) << 1;
230        self
231    }
232
233    pub fn set_set_user_identifier(mut self, set_uid: bool) -> Self {
234        self.0 = (self.0 & 0b011) | (set_uid as u8) << 2;
235        self
236    }
237
238    pub const fn get_sticky(&self) -> bool {
239        self.0 & 0b001 != 0
240    }
241
242    pub const fn get_set_group_identifier(&self) -> bool {
243        self.0 & 0b010 != 0
244    }
245
246    pub const fn get_set_user_identifier(&self) -> bool {
247        self.0 & 0b100 != 0
248    }
249
250    pub const fn to_unix(&self) -> u8 {
251        self.0
252    }
253
254    pub fn from_unix(unix: u8) -> Option<Self> {
255        if unix > 0b111 {
256            return None;
257        }
258
259        Some(Self(unix))
260    }
261}
262
263/// Represents a permission.
264///
265/// The permission can be read, write, and execute.
266///
267/// # Examples
268///
269/// ```rust
270/// use file_system::Permission_type;
271///
272/// let read = Permission_type::Read_only;
273/// let write = Permission_type::Write_only;
274/// let execute = Permission_type::Execute_only;
275///
276/// assert!(read.get_read() && !read.get_write() && !read.get_execute());
277/// assert!(!write.get_read() && write.get_write() && !write.get_execute());
278/// assert!(!execute.get_read() && !execute.get_write() && execute.get_execute());
279/// ```
280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
281#[repr(transparent)]
282pub struct Permission(u8);
283
284impl fmt::Display for Permission {
285    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
286        let read = if self.get_read() { "r" } else { "-" };
287        let write = if self.get_write() { "w" } else { "-" };
288        let execute = if self.get_execute() { "x" } else { "-" };
289
290        write!(f, "{read}{write}{execute}")
291    }
292}
293
294impl Permission {
295    pub const READ_ONLY: Self = Self::new(true, false, false);
296    pub const WRITE_ONLY: Self = Self::new(false, true, false);
297    pub const EXECUTE_ONLY: Self = Self::new(false, false, true);
298
299    pub const READ_WRITE: Self = Self::new(true, true, false);
300    pub const WRITE_EXECUTE: Self = Self::new(false, true, true);
301    pub const READ_EXECUTE: Self = Self::new(true, false, true);
302
303    pub const NONE: Self = Self::new(false, false, false);
304    pub const FULL: Self = Self::new(true, true, true);
305
306    /// Creates a new permission.
307    pub const fn new(read: bool, write: bool, execute: bool) -> Self {
308        Self((read as u8) << 2 | (write as u8) << 1 | execute as u8)
309    }
310
311    /// Sets the read permission.
312    pub fn set_read(mut self, read: bool) -> Self {
313        self.0 = (self.0 & 0b011) | (read as u8) << 2;
314        self
315    }
316
317    /// Sets the write permission.
318    pub fn set_write(mut self, write: bool) -> Self {
319        self.0 = (self.0 & 0b101) | (write as u8) << 1;
320        self
321    }
322
323    /// Sets the execute permission.
324    pub fn set_execute(mut self, execute: bool) -> Self {
325        self.0 = (self.0 & 0b110) | execute as u8;
326        self
327    }
328
329    /// Gets the read permission.
330    pub const fn get_read(&self) -> bool {
331        self.0 & 0b100 != 0
332    }
333
334    /// Gets the write permission.
335    pub const fn get_write(&self) -> bool {
336        self.0 & 0b010 != 0
337    }
338
339    /// Gets the execute permission.
340    pub const fn get_execute(&self) -> bool {
341        self.0 & 0b001 != 0
342    }
343
344    /// Converts the permission to a Unix permission.
345    pub const fn to_unix(&self) -> u8 {
346        self.0
347    }
348
349    pub fn include(&self, other: Self) -> bool {
350        (self.0 & other.0) == other.0
351    }
352
353    /// Creates a permission from a Unix permission.
354    pub fn from_unix(unix: u8) -> Option<Self> {
355        if unix > 0b111 {
356            return None;
357        }
358
359        Some(Self(unix))
360    }
361}
362
363#[cfg(test)]
364mod tests {
365    use super::*;
366
367    #[test]
368    fn test_new_permissions() {
369        let user = Permission::new(true, false, false); // Read only
370        let group = Permission::new(false, true, false); // Write only
371        let others = Permission::new(false, false, true); // Execute only
372        let special = Special::new(true, false, true); // Sticky and set user identifier
373        let permissions = Permissions::new(user, group, others, special);
374        assert_eq!(permissions.0, 0b101_100_010_001);
375    }
376
377    #[test]
378    fn test_new_permission() {
379        assert_eq!(Permission::READ_ONLY.0, 0b100);
380        assert_eq!(Permission::WRITE_ONLY.0, 0b010);
381        assert_eq!(Permission::EXECUTE_ONLY.0, 0b001);
382        assert_eq!(Permission::READ_WRITE.0, 0b110);
383        assert_eq!(Permission::WRITE_EXECUTE.0, 0b011);
384        assert_eq!(Permission::READ_EXECUTE.0, 0b101);
385        assert_eq!(Permission::NONE.0, 0b000);
386        assert_eq!(Permission::FULL.0, 0b111);
387    }
388
389    #[test]
390    fn test_permission_type_to_unix() {
391        let read = Permission::READ_ONLY;
392        assert_eq!(read.to_unix(), 4);
393        let write = Permission::WRITE_ONLY;
394        assert_eq!(write.to_unix(), 2);
395        let execute = Permission::EXECUTE_ONLY;
396        assert_eq!(execute.to_unix(), 1);
397        let full = Permission::FULL;
398        assert_eq!(full.to_unix(), 7);
399        let none = Permission::NONE;
400        assert_eq!(none.to_unix(), 0);
401    }
402
403    #[test]
404    fn test_permission_type_from_unix() {
405        let read = Permission::from_unix(4).unwrap();
406        assert!(read.get_read() && !read.get_write() && !read.get_execute());
407        let write = Permission::from_unix(2).unwrap();
408        assert!(!write.get_read() && write.get_write() && !write.get_execute());
409        let execute = Permission::from_unix(1).unwrap();
410        assert!(!execute.get_read() && !execute.get_write() && execute.get_execute());
411        let full = Permission::from_unix(7).unwrap();
412        assert!(full.get_read() && full.get_write() && full.get_execute());
413        let no = Permission::from_unix(0).unwrap();
414        assert!(!no.get_read() && !no.get_write() && !no.get_execute());
415    }
416
417    #[test]
418    fn test_permissions_type_from_unix() {
419        let permissions = Permissions::from_octal(0b101_101_101).unwrap();
420        assert_eq!(permissions.get_user().to_unix(), 5);
421        assert_eq!(permissions.get_group().to_unix(), 5);
422        assert_eq!(permissions.get_others().to_unix(), 5);
423    }
424
425    #[test]
426    fn test_permissions_type_to_unix() {
427        let user = Permission::new(true, false, true); // Read and execute
428        let group = Permission::new(true, true, false); // Read and write
429        let others = Permission::new(false, true, true); // Write and execute
430        let special = Special::new(true, false, true); // Sticky and set user identifier
431        let permissions = Permissions::new(user, group, others, special);
432        assert_eq!(permissions.as_u16(), 0b101_101_110_011);
433    }
434
435    #[test]
436    fn test_permission_type_include() {
437        let read = Permission::READ_ONLY;
438        let write = Permission::WRITE_ONLY;
439        let read_write = Permission::READ_WRITE;
440        let read_execute = Permission::READ_EXECUTE;
441        let write_execute = Permission::WRITE_EXECUTE;
442        let execute = Permission::EXECUTE_ONLY;
443        let full = Permission::FULL;
444        let no = Permission::NONE;
445
446        assert!(full.include(read));
447        assert!(full.include(write));
448        assert!(full.include(execute));
449        assert!(full.include(read_write));
450        assert!(full.include(read_execute));
451        assert!(full.include(write_execute));
452        assert!(full.include(full));
453        assert!(full.include(no));
454
455        assert!(read.include(read));
456        assert!(!read.include(write));
457        assert!(!read.include(execute));
458        assert!(!read.include(read_write));
459        assert!(!read.include(read_execute));
460        assert!(!read.include(write_execute));
461        assert!(!read.include(full));
462        assert!(read.include(no));
463
464        assert!(!write.include(read));
465        assert!(write.include(write));
466        assert!(!write.include(execute));
467        assert!(!write.include(read_write));
468        assert!(!write.include(read_execute));
469        assert!(!write.include(write_execute));
470        assert!(!write.include(full));
471        assert!(write.include(no));
472
473        assert!(!execute.include(read));
474        assert!(!execute.include(write));
475        assert!(execute.include(execute));
476        assert!(!execute.include(read_write));
477        assert!(!execute.include(read_execute));
478        assert!(!execute.include(write_execute));
479        assert!(!execute.include(full));
480        assert!(execute.include(no));
481
482        assert!(read_write.include(read));
483        assert!(read_write.include(write));
484        assert!(!read_write.include(execute));
485        assert!(read_write.include(read_write));
486        assert!(!read_write.include(read_execute));
487        assert!(!read_write.include(write_execute));
488        assert!(!read_write.include(full));
489        assert!(read_write.include(no));
490
491        assert!(read_execute.include(read));
492        assert!(!read_execute.include(write));
493        assert!(read_execute.include(execute));
494        assert!(!read_execute.include(read_write));
495        assert!(read_execute.include(read_execute));
496        assert!(!read_execute.include(write_execute));
497        assert!(!read_execute.include(full));
498        assert!(read_execute.include(no));
499
500        assert!(!write_execute.include(read));
501        assert!(write_execute.include(write));
502        assert!(write_execute.include(execute));
503        assert!(!write_execute.include(read_write));
504        assert!(!write_execute.include(read_execute));
505        assert!(write_execute.include(write_execute));
506        assert!(!write_execute.include(full));
507        assert!(write_execute.include(no));
508
509        assert!(!no.include(read));
510        assert!(!no.include(write));
511        assert!(!no.include(execute));
512        assert!(!no.include(read_write));
513        assert!(!no.include(read_execute));
514        assert!(!no.include(write_execute));
515        assert!(!no.include(full));
516        assert!(no.include(no));
517    }
518}