1pub type Errno = libc::c_int;
21
22#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
24pub struct Error(ErrorKind);
25
26impl Error {
27 pub fn kind(&self) -> ErrorKind {
28 self.0
29 }
30}
31
32#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
34pub enum ErrorKind {
35 Fork(Errno),
36 Wait(Errno),
37 DetachSession(Errno),
38 GroupNotFound,
39 GroupContainsNul,
40 SetGroup(Errno),
41 UserNotFound,
42 UserContainsNul,
43 SetUser(Errno),
44 ChangeDirectory(Errno),
45 PathContainsNul,
46 OpenPidfile(Errno),
47 GetPidfileFlags(Errno),
48 SetPidfileFlags(Errno),
49 LockPidfile(Errno),
50 ChownPidfile(Errno),
51 OpenDevnull(Errno),
52 RedirectStreams(Errno),
53 CloseDevnull(Errno),
54 TruncatePidfile(Errno),
55 WritePid(Errno),
56 WritePidUnspecifiedError,
57 Chroot(Errno),
58}
59
60impl ErrorKind {
61 fn description(&self) -> &str {
62 match self {
63 ErrorKind::Fork(_) => "unable to fork",
64 ErrorKind::Wait(_) => "wait failed",
65 ErrorKind::DetachSession(_) => "unable to create new session",
66 ErrorKind::GroupNotFound => "unable to resolve group name to group id",
67 ErrorKind::GroupContainsNul => "group option contains NUL",
68 ErrorKind::SetGroup(_) => "unable to set group",
69 ErrorKind::UserNotFound => "unable to resolve user name to user id",
70 ErrorKind::UserContainsNul => "user option contains NUL",
71 ErrorKind::SetUser(_) => "unable to set user",
72 ErrorKind::ChangeDirectory(_) => "unable to change directory",
73 ErrorKind::PathContainsNul => "pid_file option contains NUL",
74 ErrorKind::OpenPidfile(_) => "unable to open pid file",
75 ErrorKind::GetPidfileFlags(_) => "unable get pid file flags",
76 ErrorKind::SetPidfileFlags(_) => "unable set pid file flags",
77 ErrorKind::LockPidfile(_) => "unable to lock pid file",
78 ErrorKind::ChownPidfile(_) => "unable to chown pid file",
79 ErrorKind::OpenDevnull(_) => "unable to open /dev/null",
80 ErrorKind::RedirectStreams(_) => "unable to redirect standard streams to /dev/null",
81 ErrorKind::CloseDevnull(_) => "unable to close /dev/null",
82 ErrorKind::TruncatePidfile(_) => "unable to truncate pid file",
83 ErrorKind::WritePid(_) => "unable to write self pid to pid file",
84 ErrorKind::WritePidUnspecifiedError => {
85 "unable to write self pid to pid file due to unknown reason"
86 }
87 ErrorKind::Chroot(_) => "unable to chroot into directory",
88 }
89 }
90
91 fn errno(&self) -> Option<Errno> {
92 match self {
93 ErrorKind::Fork(errno) => Some(*errno),
94 ErrorKind::Wait(errno) => Some(*errno),
95 ErrorKind::DetachSession(errno) => Some(*errno),
96 ErrorKind::GroupNotFound => None,
97 ErrorKind::GroupContainsNul => None,
98 ErrorKind::SetGroup(errno) => Some(*errno),
99 ErrorKind::UserNotFound => None,
100 ErrorKind::UserContainsNul => None,
101 ErrorKind::SetUser(errno) => Some(*errno),
102 ErrorKind::ChangeDirectory(errno) => Some(*errno),
103 ErrorKind::PathContainsNul => None,
104 ErrorKind::OpenPidfile(errno) => Some(*errno),
105 ErrorKind::GetPidfileFlags(errno) => Some(*errno),
106 ErrorKind::SetPidfileFlags(errno) => Some(*errno),
107 ErrorKind::LockPidfile(errno) => Some(*errno),
108 ErrorKind::ChownPidfile(errno) => Some(*errno),
109 ErrorKind::OpenDevnull(errno) => Some(*errno),
110 ErrorKind::RedirectStreams(errno) => Some(*errno),
111 ErrorKind::CloseDevnull(errno) => Some(*errno),
112 ErrorKind::TruncatePidfile(errno) => Some(*errno),
113 ErrorKind::WritePid(errno) => Some(*errno),
114 ErrorKind::WritePidUnspecifiedError => None,
115 ErrorKind::Chroot(errno) => Some(*errno),
116 }
117 }
118}
119
120impl std::fmt::Display for ErrorKind {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 f.write_str(self.description())?;
123 if let Some(errno) = self.errno() {
124 write!(f, ", errno {}", errno)?
125 }
126 Ok(())
127 }
128}
129
130impl std::error::Error for ErrorKind {}
131
132impl std::fmt::Display for Error {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 write!(f, "{}", self.kind())
135 }
136}
137
138impl std::error::Error for Error {}
139
140impl From<ErrorKind> for Error {
141 fn from(kind: ErrorKind) -> Self {
142 Self(kind)
143 }
144}
145
146pub trait Num {
147 fn is_err(&self) -> bool;
148}
149
150impl Num for i8 {
151 fn is_err(&self) -> bool {
152 *self == -1
153 }
154}
155
156impl Num for i16 {
157 fn is_err(&self) -> bool {
158 *self == -1
159 }
160}
161
162impl Num for i32 {
163 fn is_err(&self) -> bool {
164 *self == -1
165 }
166}
167
168impl Num for i64 {
169 fn is_err(&self) -> bool {
170 *self == -1
171 }
172}
173
174impl Num for isize {
175 fn is_err(&self) -> bool {
176 *self == -1
177 }
178}
179
180pub fn check_err<N: Num, F: FnOnce(Errno) -> ErrorKind>(ret: N, f: F) -> Result<N, ErrorKind> {
181 if ret.is_err() {
182 Err(f(errno::errno().into()))
183 } else {
184 Ok(ret)
185 }
186}