iceoryx2_bb_posix/
permission.rs

1// Copyright (c) 2023 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! Defines the [`Permission`] of a file or directory in a POSIX system.
14//! Can be used in
15//! combination with [`crate::file_descriptor::FileDescriptorManagement`] to set the
16//! credentials of [`crate::file::File`], [`crate::shared_memory::SharedMemory`] and others.
17
18use core::fmt::Display;
19use core::ops::{BitOr, BitOrAssign, Not};
20
21use alloc::string::String;
22use alloc::string::ToString;
23
24use iceoryx2_pal_posix::*;
25
26type ModeType = posix::mode_t;
27
28/// Defines the permission of a file or directory in a POSIX system.
29#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
30pub struct Permission(ModeType);
31
32impl Permission {
33    pub const OWNER_READ: Self = Self(0o0400);
34    pub const OWNER_WRITE: Self = Self(0o0200);
35    pub const OWNER_EXEC: Self = Self(0o0100);
36    pub const OWNER_ALL: Self = Self(0o0700);
37
38    pub const GROUP_READ: Self = Self(0o0040);
39    pub const GROUP_WRITE: Self = Self(0o0020);
40    pub const GROUP_EXEC: Self = Self(0o0010);
41    pub const GROUP_ALL: Self = Self(0o0070);
42
43    pub const OTHERS_READ: Self = Self(0o0004);
44    pub const OTHERS_WRITE: Self = Self(0o0002);
45    pub const OTHERS_EXEC: Self = Self(0o0001);
46    pub const OTHERS_ALL: Self = Self(0o0007);
47
48    pub const ALL: Self = Self(0o0777);
49
50    pub const SET_UID: Self = Self(0o4000);
51    pub const SET_GID: Self = Self(0o2000);
52    pub const STICKY_BIT: Self = Self(0o1000);
53
54    pub const MASK: Self = Self(0o7777);
55    pub const UNKNOWN: Self = Self(0xFFFF);
56
57    pub fn none() -> Self {
58        Self(0)
59    }
60
61    pub fn bits(&self) -> ModeType {
62        self.0
63    }
64
65    pub const fn const_bitor(self, other: Permission) -> Self {
66        Self(self.0 | other.0)
67    }
68}
69
70impl BitOrAssign for Permission {
71    fn bitor_assign(&mut self, rhs: Self) {
72        self.0 |= rhs.0;
73    }
74}
75
76impl BitOr for Permission {
77    type Output = Self;
78
79    fn bitor(self, rhs: Self) -> Self::Output {
80        Self(self.0 | rhs.0)
81    }
82}
83
84impl Not for Permission {
85    type Output = Self;
86
87    fn not(self) -> Self::Output {
88        Permission(!self.0)
89    }
90}
91
92/// Trait which allows other types like integers to be converted into [`Permission`].
93pub trait PermissionExt {
94    /// converts value into [`Permission`]
95    fn as_permission(&self) -> Permission;
96}
97
98impl PermissionExt for posix::mode_t {
99    fn as_permission(&self) -> Permission {
100        let mut p = Permission::none();
101
102        let owner = self & posix::S_IRWXU;
103        if owner & posix::S_IRUSR != 0 {
104            p |= Permission::OWNER_READ;
105        }
106        if owner & posix::S_IWUSR != 0 {
107            p |= Permission::OWNER_WRITE;
108        }
109        if owner & posix::S_IXUSR != 0 {
110            p |= Permission::OWNER_EXEC;
111        }
112
113        let group = self & posix::S_IRWXG;
114        if group & posix::S_IRGRP != 0 {
115            p |= Permission::GROUP_READ;
116        }
117        if group & posix::S_IWGRP != 0 {
118            p |= Permission::GROUP_WRITE;
119        }
120        if group & posix::S_IXGRP != 0 {
121            p |= Permission::GROUP_EXEC;
122        }
123
124        let others = self & posix::S_IRWXO;
125        if others & posix::S_IROTH != 0 {
126            p |= Permission::OTHERS_READ;
127        }
128        if others & posix::S_IWOTH != 0 {
129            p |= Permission::OTHERS_WRITE;
130        }
131        if others & posix::S_IXOTH != 0 {
132            p |= Permission::OTHERS_EXEC;
133        }
134
135        if self & posix::S_ISUID != 0 {
136            p |= Permission::SET_UID;
137        }
138        if self & posix::S_ISGID != 0 {
139            p |= Permission::SET_GID;
140        }
141
142        if self & posix::S_ISVTX != 0 {
143            p |= Permission::STICKY_BIT;
144        }
145
146        p
147    }
148}
149
150impl Permission {
151    /// Returns true when self contains the permissions of the rhs, otherwise false.
152    pub fn has(&self, rhs: Permission) -> bool {
153        (self.0 & rhs.0) != 0
154    }
155
156    /// Converts the permissions into the C type mode_t
157    pub fn as_mode(&self) -> posix::mode_t {
158        self.0
159    }
160}
161
162impl Display for Permission {
163    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164        let mut owner = "---".to_string();
165        if self.has(Permission::OWNER_READ) {
166            owner.replace_range(0..1, "r");
167        }
168        if self.has(Permission::OWNER_WRITE) {
169            owner.replace_range(1..2, "w");
170        }
171        if self.has(Permission::OWNER_EXEC) {
172            owner.replace_range(2..3, "x");
173        }
174
175        let mut group = "---".to_string();
176        if self.has(Permission::GROUP_READ) {
177            group.replace_range(0..1, "r");
178        }
179        if self.has(Permission::GROUP_WRITE) {
180            group.replace_range(1..2, "w");
181        }
182        if self.has(Permission::GROUP_EXEC) {
183            group.replace_range(2..3, "x");
184        }
185
186        let mut others = "---".to_string();
187        if self.has(Permission::OTHERS_READ) {
188            others.replace_range(0..1, "r")
189        }
190        if self.has(Permission::OTHERS_WRITE) {
191            others.replace_range(1..2, "w")
192        }
193        if self.has(Permission::OTHERS_EXEC) {
194            others.replace_range(2..3, "x")
195        }
196
197        let mut bits = String::new();
198        if self.has(Permission::STICKY_BIT) {
199            bits += "StickyBit, ";
200        }
201        if self.has(Permission::SET_UID) {
202            bits += "SetUid, ";
203        }
204        if self.has(Permission::SET_GID) {
205            bits += "SetGid, ";
206        }
207
208        if bits.is_empty() {
209            bits += "-";
210        } else {
211            bits.truncate(bits.len() - 2);
212        }
213
214        write!(f, "{owner}{group}{others}")
215    }
216}