1use crate::error::ACLError::{IoError, ValidationError};
2use acl_sys::{ACL_TYPE_ACCESS, ACL_TYPE_DEFAULT};
3use std::error::Error;
4use std::io::ErrorKind;
5use std::{fmt, io};
6
7pub(crate) const FLAG_WRITE: u32 = 0x4000_0000;
9
10#[derive(Debug)]
16#[allow(clippy::upper_case_acronyms)]
17#[allow(clippy::module_name_repetitions)]
18pub enum ACLError {
19 IoError(IoErrorDetail),
21 ValidationError(ValidationErrorDetail),
27}
28
29#[derive(Debug)]
31pub struct IoErrorDetail {
32 err: io::Error,
33 flags: u32,
34}
35
36#[derive(Debug)]
38pub struct ValidationErrorDetail {
39 _private: (),
40}
41
42impl Error for ACLError {
43 fn source(&self) -> Option<&(dyn Error + 'static)> {
45 match self {
46 ValidationError(..) => None,
47 IoError(IoErrorDetail { ref err, .. }) => Some(err),
48 }
49 }
50}
51
52impl fmt::Display for ACLError {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 match self {
55 IoError(IoErrorDetail { flags, err }) => write!(
56 f,
57 "Error {} {}: {}",
58 op_display(*flags),
59 type_display(*flags),
60 err
61 ),
62 ValidationError(_) => write!(f, "ACL failed validation"),
63 }
64 }
65}
66
67impl ACLError {
68 #[must_use]
78 pub fn kind(&self) -> ErrorKind {
79 match self {
80 ValidationError(_) => ErrorKind::InvalidData,
81 IoError(IoErrorDetail { ref err, .. }) => err.kind(),
82 }
83 }
84
85 #[must_use]
94 pub fn as_io_error(&self) -> Option<&io::Error> {
95 match self {
96 ValidationError(_) => None,
97 IoError(IoErrorDetail { ref err, .. }) => Some(err),
98 }
99 }
100
101 pub(crate) fn last_os_error(flags: u32) -> ACLError {
102 IoError(IoErrorDetail {
103 err: io::Error::last_os_error(),
104 flags,
105 })
106 }
107
108 pub(crate) fn validation_error() -> ACLError {
109 ValidationError(ValidationErrorDetail { _private: () })
110 }
111}
112
113pub(crate) fn op_display(flags: u32) -> &'static str {
115 if flags & FLAG_WRITE == FLAG_WRITE {
116 "writing"
117 } else {
118 "reading"
119 }
120}
121
122pub(crate) fn type_display(flags: u32) -> &'static str {
124 let flags = flags & !FLAG_WRITE;
125 match flags {
126 ACL_TYPE_ACCESS => "ACL",
127 ACL_TYPE_DEFAULT => "default ACL",
128 _ => panic!("Invalid flags"),
129 }
130}