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}