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