use crate::errors::AuxvReaderError;
use byteorder::{NativeEndian, ReadBytesExt};
use std::fs::File;
use std::io::{BufReader, Read};
pub type Result<T> = std::result::Result<T, AuxvReaderError>;
#[cfg(target_pointer_width = "32")]
pub type AuxvType = u32;
#[cfg(target_pointer_width = "64")]
pub type AuxvType = u64;
#[derive(Debug, PartialEq, Eq)]
pub struct AuxvPair {
pub key: AuxvType,
pub value: AuxvType,
}
pub struct ProcfsAuxvIter {
pair_size: usize,
buf: Vec<u8>,
input: BufReader<File>,
keep_going: bool,
}
impl ProcfsAuxvIter {
pub fn new(input: BufReader<File>) -> Self {
let pair_size = 2 * std::mem::size_of::<AuxvType>();
let buf: Vec<u8> = Vec::with_capacity(pair_size);
Self {
pair_size,
buf,
input,
keep_going: true,
}
}
}
impl Iterator for ProcfsAuxvIter {
type Item = Result<AuxvPair>;
fn next(&mut self) -> Option<Self::Item> {
if !self.keep_going {
return None;
}
self.keep_going = false;
self.buf = vec![0; self.pair_size];
let mut read_bytes: usize = 0;
while read_bytes < self.pair_size {
match self.input.read(&mut self.buf[read_bytes..]) {
Ok(n) => {
if n == 0 {
return Some(Err(AuxvReaderError::InvalidFormat));
}
read_bytes += n;
}
Err(x) => return Some(Err(x.into())),
}
}
let mut reader = &self.buf[..];
let aux_key = match read_long(&mut reader) {
Ok(x) => x,
Err(x) => return Some(Err(x.into())),
};
let aux_val = match read_long(&mut reader) {
Ok(x) => x,
Err(x) => return Some(Err(x.into())),
};
let at_null;
#[cfg(any(target_arch = "arm", all(target_os = "android", target_arch = "x86")))]
{
at_null = 0;
}
#[cfg(not(any(target_arch = "arm", all(target_os = "android", target_arch = "x86"))))]
{
at_null = libc::AT_NULL;
}
if aux_key == at_null {
return None;
}
self.keep_going = true;
Some(Ok(AuxvPair {
key: aux_key,
value: aux_val,
}))
}
}
fn read_long(reader: &mut dyn Read) -> std::io::Result<AuxvType> {
match std::mem::size_of::<AuxvType>() {
4 => reader.read_u32::<NativeEndian>().map(|u| u as AuxvType),
8 => reader.read_u64::<NativeEndian>().map(|u| u as AuxvType),
x => panic!("Unexpected type width: {}", x),
}
}