use std::ops::{Deref, DerefMut};
use std::sync::atomic;
use crate::{Key, Keyring, KeyringSerial, SpecialKeyring};
pub mod kernel;
pub mod keys;
#[derive(Debug)]
pub struct ScopedKeyring {
keyring: Keyring,
}
impl Drop for ScopedKeyring {
fn drop(&mut self) {
self.keyring.clone().invalidate().unwrap();
wait_for_keyring_gc(&self.keyring);
}
}
impl Deref for ScopedKeyring {
type Target = Keyring;
fn deref(&self) -> &Self::Target {
&self.keyring
}
}
impl DerefMut for ScopedKeyring {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.keyring
}
}
pub fn new_test_keyring_manual() -> Keyring {
let mut thread_keyring = Keyring::attach_or_create(SpecialKeyring::Thread).unwrap();
static KEYRING_COUNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
let num = KEYRING_COUNT.fetch_add(1, atomic::Ordering::SeqCst);
thread_keyring
.add_keyring(format!("test:rust-keyutils{}", num))
.unwrap()
}
pub fn new_test_keyring() -> ScopedKeyring {
ScopedKeyring {
keyring: new_test_keyring_manual(),
}
}
unsafe fn invalid_serial() -> KeyringSerial {
KeyringSerial::new_unchecked(0)
}
pub fn invalid_keyring() -> Keyring {
unsafe { Keyring::new(invalid_serial()) }
}
pub fn invalid_key() -> Key {
unsafe { Key::new(invalid_serial()) }
}
pub fn keyring_as_key(keyring: &Keyring) -> Key {
unsafe { Key::new(keyring.serial()) }
}
pub fn key_as_keyring(key: &Key) -> Keyring {
unsafe { Keyring::new(key.serial()) }
}
pub fn wait_for_key_gc(key: &Key) {
loop {
match key.description() {
Ok(_) => (),
Err(errno::Errno(libc::ENOKEY)) => break,
e @ Err(_) => {
e.unwrap();
unreachable!()
},
}
}
}
pub fn wait_for_keyring_gc(keyring: &Keyring) {
loop {
match keyring.read() {
Ok(_) | Err(errno::Errno(libc::EACCES)) => (),
Err(errno::Errno(libc::ENOKEY)) => break,
e @ Err(_) => {
e.unwrap();
unreachable!()
},
}
}
}