firecracker_rs_sdk/
fstack.rs

1use std::{fs, path::PathBuf, process::Command};
2
3use log::{error, info};
4
5pub struct FStack {
6    inner: Vec<FStackAction>,
7}
8
9pub enum FStackAction {
10    RemoveDirectory(PathBuf),
11    RemoveFile(PathBuf),
12    TerminateProcess(u32),
13}
14
15impl Drop for FStack {
16    fn drop(&mut self) {
17        while let Some(action) = self.inner.pop() {
18            match action {
19                FStackAction::RemoveDirectory(dir) => {
20                    info!("FStack: performing `RemoveDirectory({})`", dir.display());
21                    let dir: PathBuf = dir.into();
22                    if dir.exists() && dir.is_dir() {
23                        let _ = fs::remove_dir_all(&dir);
24                    } else {
25                        error!("FStack: {} does not exist!", dir.display());
26                    }
27                }
28                FStackAction::RemoveFile(path) => {
29                    info!("FStack: performing `RemoveFile({})`", path.display());
30                    if let Err(e) = fs::remove_file(&path) {
31                        error!("FStack: fail to remove file {}: {e}", path.display());
32                        /* We could do nothing on error though... */
33                    }
34                }
35                FStackAction::TerminateProcess(pid) => {
36                    info!("FStack: performing `TerminateProcess({})`", pid);
37                    match Command::new("kill")
38                        .arg("-15")
39                        .arg(pid.to_string())
40                        .output()
41                    {
42                        Ok(_output) => {
43                            info!("FStack: killed process {pid}");
44                        }
45                        Err(e) => {
46                            error!("FStack: fail to terminate process {pid}: {e}");
47                        }
48                    }
49                }
50            }
51        }
52    }
53}
54
55impl FStack {
56    pub fn new() -> Self {
57        FStack { inner: Vec::new() }
58    }
59
60    pub fn push_action(&mut self, action: FStackAction) {
61        self.inner.push(action);
62    }
63
64    /// Drop this FStackStack without rollback.
65    /// Called when we are sure that everything is running well and
66    /// do not need rollback.
67    pub fn cancel(mut self) {
68        self.inner.clear();
69        info!("FStack: stack cancelled, are we going well?");
70    }
71}