mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-11 04:49:48 +00:00
167 lines
4.0 KiB
Rust
167 lines
4.0 KiB
Rust
//! This is a general utility crate used by all our rust projects.
|
|
|
|
use failure::*;
|
|
use lazy_static::lazy_static;
|
|
|
|
pub mod borrow;
|
|
pub mod common_regex;
|
|
pub mod fd;
|
|
pub mod fs;
|
|
pub mod io;
|
|
pub mod serde;
|
|
pub mod vec;
|
|
|
|
/// Evaluates to the offset (in bytes) of a given member within a struct
|
|
#[macro_export]
|
|
macro_rules! offsetof {
|
|
($ty:ty, $field:ident) => {
|
|
unsafe { &(*(0 as *const $ty)).$field as *const _ as usize }
|
|
};
|
|
}
|
|
|
|
/// Macro to write error-handling blocks (like perl eval {})
|
|
///
|
|
/// #### Example:
|
|
/// ```
|
|
/// # use proxmox_tools::try_block;
|
|
/// # use failure::*;
|
|
/// # let some_condition = false;
|
|
/// let result = try_block!({
|
|
/// if (some_condition) {
|
|
/// bail!("some error");
|
|
/// }
|
|
/// Ok(())
|
|
/// })
|
|
/// .map_err(|e| format_err!("my try block returned an error - {}", e));
|
|
/// ```
|
|
|
|
#[macro_export]
|
|
macro_rules! try_block {
|
|
{ $($token:tt)* } => {{ (|| -> Result<_,_> { $($token)* })() }}
|
|
}
|
|
|
|
const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
|
|
|
|
pub fn digest_to_hex(digest: &[u8]) -> String {
|
|
bin_to_hex(digest)
|
|
}
|
|
|
|
/// Convert a byte slice to a string of hexadecimal digits.
|
|
///
|
|
/// ```
|
|
/// # use proxmox_tools::bin_to_hex;
|
|
///
|
|
/// let text = bin_to_hex(&[1, 2, 0xff]);
|
|
/// assert_eq!(text, "0102ff");
|
|
/// ```
|
|
pub fn bin_to_hex(digest: &[u8]) -> String {
|
|
let mut buf = Vec::<u8>::with_capacity(digest.len() * 2);
|
|
|
|
for i in 0..digest.len() {
|
|
buf.push(HEX_CHARS[(digest[i] >> 4) as usize]);
|
|
buf.push(HEX_CHARS[(digest[i] & 0xf) as usize]);
|
|
}
|
|
|
|
unsafe { String::from_utf8_unchecked(buf) }
|
|
}
|
|
|
|
/// Convert a string of hexadecimal digits to a byte vector. Any non-digits are treated as an
|
|
/// error, so when there is possible whitespace in the string it must be stripped by the caller
|
|
/// first. Also, only full bytes are allowed, so the input must consist of an even number of
|
|
/// digits.
|
|
///
|
|
/// ```
|
|
/// # use proxmox_tools::hex_to_bin;
|
|
///
|
|
/// let data = hex_to_bin("aabb0123").unwrap();
|
|
/// assert_eq!(&data, &[0xaa, 0xbb, 0x01, 0x23]);
|
|
/// ```
|
|
pub fn hex_to_bin(hex: &str) -> Result<Vec<u8>, Error> {
|
|
let mut result = vec![];
|
|
|
|
let bytes = hex.as_bytes();
|
|
|
|
if (bytes.len() % 2) != 0 {
|
|
bail!("hex_to_bin: got wrong input length.");
|
|
}
|
|
|
|
let val = |c| {
|
|
if c >= b'0' && c <= b'9' {
|
|
return Ok(c - b'0');
|
|
}
|
|
if c >= b'a' && c <= b'f' {
|
|
return Ok(c - b'a' + 10);
|
|
}
|
|
if c >= b'A' && c <= b'F' {
|
|
return Ok(c - b'A' + 10);
|
|
}
|
|
bail!("found illegal hex character.");
|
|
};
|
|
|
|
for pair in bytes.chunks(2) {
|
|
let h = val(pair[0])?;
|
|
let l = val(pair[1])?;
|
|
result.push((h << 4) | l);
|
|
}
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
// FIXME: This should be renamed to contain the digest algorithm, so that the array's size makes
|
|
// sense.
|
|
pub fn hex_to_digest(hex: &str) -> Result<[u8; 32], Error> {
|
|
let mut digest = [0u8; 32];
|
|
|
|
let bytes = hex.as_bytes();
|
|
|
|
if bytes.len() != 64 {
|
|
bail!("got wrong digest length.");
|
|
}
|
|
|
|
let val = |c| {
|
|
if c >= b'0' && c <= b'9' {
|
|
return Ok(c - b'0');
|
|
}
|
|
if c >= b'a' && c <= b'f' {
|
|
return Ok(c - b'a' + 10);
|
|
}
|
|
if c >= b'A' && c <= b'F' {
|
|
return Ok(c - b'A' + 10);
|
|
}
|
|
bail!("found illegal hex character.");
|
|
};
|
|
|
|
let mut pos = 0;
|
|
for pair in bytes.chunks(2) {
|
|
if pos >= digest.len() {
|
|
bail!("hex digest too long.");
|
|
}
|
|
let h = val(pair[0])?;
|
|
let l = val(pair[1])?;
|
|
digest[pos] = (h << 4) | l;
|
|
pos += 1;
|
|
}
|
|
|
|
if pos != digest.len() {
|
|
bail!("hex digest too short.");
|
|
}
|
|
|
|
Ok(digest)
|
|
}
|
|
|
|
/// Returns the hosts node name (UTS node name)
|
|
pub fn nodename() -> &'static str {
|
|
lazy_static! {
|
|
static ref NODENAME: String = {
|
|
nix::sys::utsname::uname()
|
|
.nodename()
|
|
.split('.')
|
|
.next()
|
|
.unwrap()
|
|
.to_owned()
|
|
};
|
|
}
|
|
|
|
&NODENAME
|
|
}
|