qemu_command_builder/args/
sandbox.rs1use crate::common::OnOff;
2use crate::parsers::{ARG_SANDBOX, DELIM_COMMA};
3use crate::to_command::{ToArg, ToCommand};
4use bon::Builder;
5use proptest_derive::Arbitrary;
6use std::str::FromStr;
7
8#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
9pub enum AllowDeny {
10 Allow,
11 Deny,
12}
13
14impl ToArg for AllowDeny {
15 fn to_arg(&self) -> &str {
16 match self {
17 AllowDeny::Allow => "allow",
18 AllowDeny::Deny => "deny",
19 }
20 }
21}
22#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
23pub enum AllowDenyChildren {
24 Allow,
25 Deny,
26 Children,
27}
28
29impl ToArg for AllowDenyChildren {
30 fn to_arg(&self) -> &str {
31 match self {
32 AllowDenyChildren::Allow => "allow",
33 AllowDenyChildren::Deny => "deny",
34 AllowDenyChildren::Children => "children",
35 }
36 }
37}
38#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
39pub struct Sandbox {
40 mode: OnOff,
42 obsolete: Option<AllowDeny>,
44 elevateprivileges: Option<AllowDenyChildren>,
46 spawn: Option<AllowDeny>,
48 resourcecontrol: Option<AllowDeny>,
50}
51
52impl ToCommand for Sandbox {
53 fn command(&self) -> String {
54 ARG_SANDBOX.to_string()
55 }
56 fn to_args(&self) -> Vec<String> {
57 let mut args = vec![];
58 args.push(self.mode.to_arg().to_string());
59
60 if let Some(obsolete) = &self.obsolete {
61 args.push(format!("obsolete={}", obsolete.to_arg()));
62 }
63 if let Some(elevateprivileges) = &self.elevateprivileges {
64 args.push(format!("elevateprivileges={}", elevateprivileges.to_arg()))
65 }
66 if let Some(spawn) = &self.spawn {
67 args.push(format!("spawn={}", spawn.to_arg()));
68 }
69 if let Some(resourcecontrol) = &self.resourcecontrol {
70 args.push(format!("resourcecontrol={}", resourcecontrol.to_arg()));
71 }
72
73 vec![args.join(DELIM_COMMA)]
74 }
75}
76
77impl FromStr for Sandbox {
78 type Err = String;
79
80 fn from_str(s: &str) -> Result<Self, Self::Err> {
81 let mut parts = s.split(DELIM_COMMA);
82 let mode = parts
83 .next()
84 .ok_or_else(|| "empty -sandbox argument".to_string())?
85 .parse::<OnOff>()
86 .map_err(|_| format!("invalid sandbox mode: {s}"))?;
87
88 let mut obsolete = None;
89 let mut elevateprivileges = None;
90 let mut spawn = None;
91 let mut resourcecontrol = None;
92
93 for part in parts {
94 let (key, value) = part.split_once('=').ok_or_else(|| format!("invalid -sandbox option: {part}"))?;
95 match key {
96 "obsolete" => {
97 obsolete = Some(match value {
98 "allow" => AllowDeny::Allow,
99 "deny" => AllowDeny::Deny,
100 _ => return Err(format!("invalid obsolete value: {value}")),
101 })
102 }
103 "elevateprivileges" => {
104 elevateprivileges = Some(match value {
105 "allow" => AllowDenyChildren::Allow,
106 "deny" => AllowDenyChildren::Deny,
107 "children" => AllowDenyChildren::Children,
108 _ => return Err(format!("invalid elevateprivileges value: {value}")),
109 })
110 }
111 "spawn" => {
112 spawn = Some(match value {
113 "allow" => AllowDeny::Allow,
114 "deny" => AllowDeny::Deny,
115 _ => return Err(format!("invalid spawn value: {value}")),
116 })
117 }
118 "resourcecontrol" => {
119 resourcecontrol = Some(match value {
120 "allow" => AllowDeny::Allow,
121 "deny" => AllowDeny::Deny,
122 _ => return Err(format!("invalid resourcecontrol value: {value}")),
123 })
124 }
125 other => return Err(format!("unsupported -sandbox option: {other}")),
126 }
127 }
128
129 Ok(Self {
130 mode,
131 obsolete,
132 elevateprivileges,
133 spawn,
134 resourcecontrol,
135 })
136 }
137}