comparison src/constants.rs @ 84:a638a45e5f1f

do some real irritating i32/u32 juggling to make bindgen happy
author Paul Fisher <paul@pfish.zone>
date Tue, 10 Jun 2025 02:35:11 -0400
parents 5aa1a010f1e8
children 5e14bb093851
comparison
equal deleted inserted replaced
83:9fc778c03bff 84:a638a45e5f1f
3 #[cfg(feature = "link")] 3 #[cfg(feature = "link")]
4 use crate::libpam::pam_ffi; 4 use crate::libpam::pam_ffi;
5 use bitflags::bitflags; 5 use bitflags::bitflags;
6 use libc::c_int; 6 use libc::c_int;
7 use num_enum::{IntoPrimitive, TryFromPrimitive}; 7 use num_enum::{IntoPrimitive, TryFromPrimitive};
8 use std::ffi::c_uint;
8 use std::result::Result as StdResult; 9 use std::result::Result as StdResult;
9 10
10 /// Arbitrary values for PAM constants when not linking against system PAM. 11 /// Arbitrary values for PAM constants when not linking against system PAM.
11 /// 12 ///
12 /// **The values of these constants are deliberately selected _not_ to match 13 /// **The values of these constants are deliberately selected _not_ to match
16 mod ffi { 17 mod ffi {
17 macro_rules! define { 18 macro_rules! define {
18 ($(#[$attr:meta])* $($name:ident = $value:expr),+) => { 19 ($(#[$attr:meta])* $($name:ident = $value:expr),+) => {
19 define!( 20 define!(
20 @meta { $(#[$attr])* } 21 @meta { $(#[$attr])* }
21 $(pub const $name: i32 = $value;)+ 22 $(pub const $name: u32 = $value;)+
22 ); 23 );
23 }; 24 };
24 (@meta $m:tt $($i:item)+) => { define!(@expand $($m $i)+); }; 25 (@meta $m:tt $($i:item)+) => { define!(@expand $($m $i)+); };
25 (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+}; 26 (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+};
26 } 27 }
27 const fn bit(n: i8) -> i32 { 28 const fn bit(n: u8) -> u32 {
28 1 << n 29 1 << n
29 } 30 }
30 define!( 31 define!(
31 PAM_SILENT = bit(13), 32 PAM_SILENT = bit(13),
32 PAM_DISALLOW_NULL_AUTHTOK = bit(14), 33 PAM_DISALLOW_NULL_AUTHTOK = bit(14),
79 /// 80 ///
80 /// See `/usr/include/security/_pam_types.h` and 81 /// See `/usr/include/security/_pam_types.h` and
81 /// See `/usr/include/security/pam_modules.h` for more details. 82 /// See `/usr/include/security/pam_modules.h` for more details.
82 #[derive(Debug, PartialEq)] 83 #[derive(Debug, PartialEq)]
83 #[repr(transparent)] 84 #[repr(transparent)]
84 pub struct Flags: c_int { 85 pub struct Flags: c_uint {
85 /// The module should not generate any messages. 86 /// The module should not generate any messages.
86 const SILENT = pam_ffi::PAM_SILENT; 87 const SILENT = pam_ffi::PAM_SILENT;
87 88
88 /// The module should return [ErrorCode::AuthError] 89 /// The module should return [ErrorCode::AuthError]
89 /// if the user has an empty authentication token 90 /// if the user has an empty authentication token
136 /// For more detailed information, see 137 /// For more detailed information, see
137 /// `/usr/include/security/_pam_types.h`. 138 /// `/usr/include/security/_pam_types.h`.
138 #[allow(non_camel_case_types, dead_code)] 139 #[allow(non_camel_case_types, dead_code)]
139 #[derive(Copy, Clone, Debug, PartialEq, thiserror::Error, TryFromPrimitive, IntoPrimitive)] 140 #[derive(Copy, Clone, Debug, PartialEq, thiserror::Error, TryFromPrimitive, IntoPrimitive)]
140 #[non_exhaustive] // C might give us anything! 141 #[non_exhaustive] // C might give us anything!
141 #[repr(i32)] 142 #[repr(u32)]
142 pub enum ErrorCode { 143 pub enum ErrorCode {
143 #[error("dlopen() failure when dynamically loading a service module")] 144 #[error("dlopen() failure when dynamically loading a service module")]
144 OpenError = pam_ffi::PAM_OPEN_ERR, 145 OpenError = pam_ffi::PAM_OPEN_ERR,
145 #[error("symbol not found")] 146 #[error("symbol not found")]
146 SymbolError = pam_ffi::PAM_SYMBOL_ERR, 147 SymbolError = pam_ffi::PAM_SYMBOL_ERR,
210 impl ErrorCode { 211 impl ErrorCode {
211 /// Converts this [Result] into a C-compatible result code. 212 /// Converts this [Result] into a C-compatible result code.
212 pub fn result_to_c<T>(value: Result<T>) -> c_int { 213 pub fn result_to_c<T>(value: Result<T>) -> c_int {
213 match value { 214 match value {
214 Ok(_) => 0, // PAM_SUCCESS 215 Ok(_) => 0, // PAM_SUCCESS
215 Err(otherwise) => otherwise.into(), 216 Err(otherwise) => u32::from(otherwise) as i32,
216 } 217 }
217 } 218 }
218 219
219 /// Converts a C result code into a [Result], with success as Ok. 220 /// Converts a C result code into a [Result], with success as Ok.
220 /// Invalid values are returned as a [Self::SystemError]. 221 /// Invalid values are returned as a [Self::SystemError].
221 pub fn result_from(value: c_int) -> Result<()> { 222 pub fn result_from(value: c_int) -> Result<()> {
222 match value { 223 match value {
223 0 => Ok(()), 224 0 => Ok(()),
224 value => Err(value.try_into().unwrap_or(Self::SystemError)), 225 value => Err((value as u32).try_into().unwrap_or(Self::SystemError)),
225 } 226 }
226 } 227 }
227 } 228 }
228 229
229 /// Returned when text that should not have any `\0` bytes in it does. 230 /// Returned when text that should not have any `\0` bytes in it does.
235 236
236 #[test] 237 #[test]
237 fn test_enums() { 238 fn test_enums() {
238 assert_eq!(Ok(()), ErrorCode::result_from(0)); 239 assert_eq!(Ok(()), ErrorCode::result_from(0));
239 assert_eq!( 240 assert_eq!(
240 pam_ffi::PAM_BAD_ITEM, 241 pam_ffi::PAM_BAD_ITEM as i32,
241 ErrorCode::result_to_c::<()>(Err(ErrorCode::BadItem)) 242 ErrorCode::result_to_c::<()>(Err(ErrorCode::BadItem))
242 ); 243 );
243 assert_eq!( 244 assert_eq!(
244 Err(ErrorCode::Abort), 245 Err(ErrorCode::Abort),
245 ErrorCode::result_from(pam_ffi::PAM_ABORT) 246 ErrorCode::result_from(pam_ffi::PAM_ABORT as i32)
246 ); 247 );
247 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423)); 248 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423));
248 } 249 }
249 } 250 }