file_system/fundamentals/
permission.rs1use core::fmt;
2
3use crate::Kind;
4
5#[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 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 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 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 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 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 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 pub fn get_user(&self) -> Permission {
158 Permission::from_unix(((self.0 >> 6) & 0b111) as u8).unwrap()
159 }
160
161 pub fn get_group(&self) -> Permission {
163 Permission::from_unix(((self.0 >> 3) & 0b111) as u8).unwrap()
164 }
165
166 pub fn get_others(&self) -> Permission {
168 Permission::from_unix((self.0 & 0b111) as u8).unwrap()
169 }
170
171 pub fn get_special(&self) -> Special {
173 Special::from_unix((self.0 >> 9) as u8).unwrap()
174 }
175
176 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 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#[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 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 pub fn set_read(mut self, read: bool) -> Self {
313 self.0 = (self.0 & 0b011) | (read as u8) << 2;
314 self
315 }
316
317 pub fn set_write(mut self, write: bool) -> Self {
319 self.0 = (self.0 & 0b101) | (write as u8) << 1;
320 self
321 }
322
323 pub fn set_execute(mut self, execute: bool) -> Self {
325 self.0 = (self.0 & 0b110) | execute as u8;
326 self
327 }
328
329 pub const fn get_read(&self) -> bool {
331 self.0 & 0b100 != 0
332 }
333
334 pub const fn get_write(&self) -> bool {
336 self.0 & 0b010 != 0
337 }
338
339 pub const fn get_execute(&self) -> bool {
341 self.0 & 0b001 != 0
342 }
343
344 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 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); let group = Permission::new(false, true, false); let others = Permission::new(false, false, true); let special = Special::new(true, false, true); 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); let group = Permission::new(true, true, false); let others = Permission::new(false, true, true); let special = Special::new(true, false, true); 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}