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