bsudlib/
utils.rs

1use easy_error::format_err;
2use log::trace;
3use std::error::Error;
4use std::process::Command;
5use std::process::Stdio;
6
7const NB_OF_BYTES_IN_GIB: usize = 1024_usize.pow(3);
8
9pub fn bytes_to_gib(bytes: usize) -> f32 {
10    bytes as f32 / NB_OF_BYTES_IN_GIB as f32
11}
12
13pub fn bytes_to_gib_rounded(bytes: usize) -> usize {
14    bytes_to_gib(bytes).ceil() as usize
15}
16
17pub fn gib_to_bytes(gib: usize) -> usize {
18    gib * NB_OF_BYTES_IN_GIB
19}
20
21pub struct ExecOutput {
22    pub success: bool,
23    pub stdout: String,
24    pub stderr: String,
25}
26
27fn cmd_str(cmd: &str, args: &[&str]) -> String {
28    let mut concatenated_arg = String::from(cmd);
29    for arg in args {
30        concatenated_arg += " ";
31        concatenated_arg += arg;
32    }
33    concatenated_arg
34}
35
36fn exec_raw(cmd: &str, args: &[&str]) -> Result<ExecOutput, Box<dyn Error>> {
37    let cmd_str = cmd_str(cmd, args);
38    trace!("exec {}", cmd_str);
39    let output = Command::new(cmd)
40        .args(args)
41        .stdout(Stdio::piped())
42        .stdout(Stdio::piped())
43        .output()?;
44    let stdout = String::from_utf8(output.stdout)?;
45    let stderr = String::from_utf8(output.stderr)?;
46    let success = output.status.success();
47    if !success {
48        if !stdout.is_empty() {
49            trace!("{} stdout: {}", cmd_str, stdout);
50        }
51        if !stderr.is_empty() {
52            trace!("{} stderr: {}", cmd_str, stderr);
53        }
54    }
55    Ok(ExecOutput {
56        success,
57        stdout,
58        stderr,
59    })
60}
61
62pub fn exec(cmd: &str, args: &[&str]) -> Result<ExecOutput, Box<dyn Error>> {
63    let output = exec_raw(cmd, args)?;
64    if !output.success {
65        return Err(Box::new(format_err!("{} {:?} exited non zero", cmd, args)));
66    }
67    Ok(output)
68}
69
70pub fn exec_bool(cmd: &str, args: &[&str]) -> Result<bool, Box<dyn Error>> {
71    let output = exec_raw(cmd, args)?;
72    Ok(output.success)
73}