hadoop_common/fs/permission/
fs_permission.rs

1use super::{fs_action::FSACTION_VALUES, FsAction, UmaskParser};
2use crate::{
3    conf::Configuration,
4    fs::common_configuration_keys::{FS_PERMISSIONS_UMASK_DEFAULT, FS_PERMISSIONS_UMASK_KEY},
5};
6use hadoop_proto::hadoop::hdfs::FsPermissionProto;
7use once_cell::sync::Lazy;
8
9const UMASK_LABEL: &str = FS_PERMISSIONS_UMASK_KEY;
10const DEFAULT_UMASK: i32 = FS_PERMISSIONS_UMASK_DEFAULT;
11
12/// Default permission for directory
13pub static DIR_DEFAULT_PERM: Lazy<FsPermission> = Lazy::new(FsPermission::get_dir_default);
14/// Default permission for file
15pub static FILE_DEFAULT_PERM: Lazy<FsPermission> = Lazy::new(FsPermission::get_file_default);
16
17#[derive(Clone, Copy)]
18pub struct FsPermission {
19    useraction: FsAction,
20    groupaction: FsAction,
21    otheraction: FsAction,
22    sticky_bit: bool,
23}
24
25impl FsPermission {
26    fn parse_short(n: i16) -> (FsAction, FsAction, FsAction, bool) {
27        (
28            FSACTION_VALUES[(n >> 6 & 7) as usize],
29            FSACTION_VALUES[(n >> 3 & 7) as usize],
30            FSACTION_VALUES[(n & 7) as usize],
31            n >> 9 & 1 == 1,
32        )
33    }
34
35    pub fn update_short(&mut self, n: i16) {
36        let (u, g, o, sb) = Self::parse_short(n);
37        self.useraction = u;
38        self.groupaction = g;
39        self.otheraction = o;
40        self.sticky_bit = sb;
41    }
42
43    /// Encode the object to a short.
44    pub fn to_short(&self) -> i16 {
45        (if self.sticky_bit { 1 << 9 } else { 0 })
46            | (self.useraction.ordinal() << 6) as i16
47            | (self.groupaction.ordinal() << 3) as i16
48            | self.otheraction.ordinal() as i16
49    }
50
51    /// Apply a umask to this permission and return a new one.
52    ///
53    /// The umask is used by create, mkdir, and other Hadoop filesystem operations.
54    /// The mode argument for these operations is modified by removing the bits
55    /// which are set in the umask.  Thus, the umask limits the permissions which
56    /// newly created files and directories get.
57    pub fn apply_umask(&self, umask: &FsPermission) -> Self {
58        Self {
59            useraction: self.useraction.and(&umask.useraction.not()),
60            groupaction: self.groupaction.and(&umask.groupaction.not()),
61            otheraction: self.otheraction.and(&umask.otheraction.not()),
62            sticky_bit: false,
63        }
64    }
65
66    /// Get the user file creation mask (umask)
67    ///
68    /// [`UMASK_LABEL`] config param has umask value that is either symbolic
69    /// or octal.
70    ///
71    /// Symbolic umask is applied relative to file mode creation mask;
72    /// the permission op characters '+' clears the corresponding bit in the mask,
73    /// '-' sets bits in the mask.
74    ///
75    /// Octal umask, the specified bits are set in the file mode creation mask.
76    pub fn get_umask(conf: Option<&Configuration>) -> anyhow::Result<Self> {
77        let mut umask = DEFAULT_UMASK as i16;
78        // To ensure backward compatibility first use the deprecated key.
79        // If the deprecated key is not present then check for the new key
80        if let Some(conf) = conf {
81            if let Some(conf_umask) = conf.get(UMASK_LABEL, None) {
82                umask = UmaskParser::new(conf_umask)?.get_umask();
83            }
84        }
85        Ok(Self::from(umask))
86    }
87
88    /// Get the default permission for directory.
89    pub fn get_dir_default() -> Self {
90        Self::from(0o777)
91    }
92
93    /// Get the default permission for file.
94    pub fn get_file_default() -> Self {
95        Self::from(0o666)
96    }
97}
98
99impl From<i16> for FsPermission {
100    /// Construct by the given mode.
101    fn from(mode: i16) -> Self {
102        let (u, g, o, sb) = Self::parse_short(mode);
103        Self {
104            useraction: u,
105            groupaction: g,
106            otheraction: o,
107            sticky_bit: sb,
108        }
109    }
110}
111
112impl Into<FsPermissionProto> for &FsPermission {
113    fn into(self) -> FsPermissionProto {
114        FsPermissionProto {
115            perm: self.to_short() as u32,
116        }
117    }
118}