1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use easy_error::format_err;
use log::trace;
use std::error::Error;
use std::process::Command;
use std::process::Stdio;

const NB_OF_BYTES_IN_GIB: usize = 1024_usize.pow(3);

pub fn bytes_to_gib(bytes: usize) -> f32 {
    bytes as f32 / NB_OF_BYTES_IN_GIB as f32
}

pub fn bytes_to_gib_rounded(bytes: usize) -> usize {
    bytes_to_gib(bytes).ceil() as usize
}

pub fn gib_to_bytes(gib: usize) -> usize {
    gib * NB_OF_BYTES_IN_GIB
}

pub struct ExecOutput {
    pub success: bool,
    pub stdout: String,
    pub stderr: String,
}

fn cmd_str(cmd: &str, args: &[&str]) -> String {
    let mut concatenated_arg = String::from(cmd);
    for arg in args {
        concatenated_arg += " ";
        concatenated_arg += arg;
    }
    concatenated_arg
}

fn exec_raw(cmd: &str, args: &[&str]) -> Result<ExecOutput, Box<dyn Error>> {
    let cmd_str = cmd_str(cmd, args);
    trace!("exec {}", cmd_str);
    let output = Command::new(cmd)
        .args(args)
        .stdout(Stdio::piped())
        .stdout(Stdio::piped())
        .output()?;
    let stdout = String::from_utf8(output.stdout)?;
    let stderr = String::from_utf8(output.stderr)?;
    let success = output.status.success();
    if !success {
        if !stdout.is_empty() {
            trace!("{} stdout: {}", cmd_str, stdout);
        }
        if !stderr.is_empty() {
            trace!("{} stderr: {}", cmd_str, stderr);
        }
    }
    Ok(ExecOutput {
        success,
        stdout,
        stderr,
    })
}

pub fn exec(cmd: &str, args: &[&str]) -> Result<ExecOutput, Box<dyn Error>> {
    let output = exec_raw(cmd, args)?;
    if !output.success {
        return Err(Box::new(format_err!("{} {:?} exited non zero", cmd, args)));
    }
    Ok(output)
}

pub fn exec_bool(cmd: &str, args: &[&str]) -> Result<bool, Box<dyn Error>> {
    let output = exec_raw(cmd, args)?;
    Ok(output.success)
}