diff options
author | Dmitry Torokhov <dtor@chromium.org> | 2019-12-13 11:47:52 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-18 01:11:47 +0000 |
commit | 458bb643441bc122fe7b39e1c0f526b4d5bd976a (patch) | |
tree | 7974aa07e93cc89e2f11664dc003db5d41bde772 /src/main.rs | |
parent | 5aef6474862a94c85ac90757fe8ba7376a3ed1d6 (diff) | |
download | crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar.gz crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar.bz2 crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar.lz crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar.xz crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.tar.zst crosvm-458bb643441bc122fe7b39e1c0f526b4d5bd976a.zip |
crosvm: allow shorthand notation in plugin-mount and plugin-gid-map
Let's allow shorthand notation in the form of: --plugin-mount=<src>[:[<dst>][:<writable>]] --plugin-gid-map=<inner>[:[<outer>][:<count>]] so that we can invoke crosvm as crosvm ... --plugin-mount=/bin --plugin-mount=/dev/log::true \ --plugin-gid-map=123 --plugin-gid-map=567::5 as repeating the data for both src and destination muddies the waters and is prone to errors. BUG=None TEST=cargo test Change-Id: I6f0a075ea3b27d4ec3dcf88698069930c158e759 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1967786 Reviewed-by: Zach Reizner <zachr@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Dmitry Torokhov <dtor@chromium.org>
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 129 |
1 files changed, 112 insertions, 17 deletions
diff --git a/src/main.rs b/src/main.rs index 0e11ee1..c8dda2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -270,10 +270,10 @@ fn parse_serial_options(s: &str) -> argument::Result<SerialParameters> { fn parse_plugin_mount_option(value: &str) -> argument::Result<BindMount> { let components: Vec<&str> = value.split(":").collect(); - if components.len() != 3 { + if components.is_empty() || components.len() > 3 || components[0].is_empty() { return Err(argument::Error::InvalidValue { value: value.to_owned(), - expected: "`plugin-mount` must have exactly 3 components: <src>:<dst>:<writable>", + expected: "`plugin-mount` should be in a form of: <src>[:[<dst>][:<writable>]]", }); } @@ -291,7 +291,10 @@ fn parse_plugin_mount_option(value: &str) -> argument::Result<BindMount> { }); } - let dst = PathBuf::from(components[1]); + let dst = PathBuf::from(match components.get(1) { + None | Some(&"") => components[0], + Some(path) => path, + }); if dst.is_relative() { return Err(argument::Error::InvalidValue { value: components[1].to_owned(), @@ -299,22 +302,24 @@ fn parse_plugin_mount_option(value: &str) -> argument::Result<BindMount> { }); } - let writable: bool = components[2] - .parse() - .map_err(|_| argument::Error::InvalidValue { + let writable: bool = match components.get(2) { + None => false, + Some(s) => s.parse().map_err(|_| argument::Error::InvalidValue { value: components[2].to_owned(), expected: "the <writable> component for `plugin-mount` is not valid bool", - })?; + })?, + }; Ok(BindMount { src, dst, writable }) } fn parse_plugin_gid_map_option(value: &str) -> argument::Result<GidMap> { let components: Vec<&str> = value.split(":").collect(); - if components.len() != 3 { + if components.is_empty() || components.len() > 3 || components[0].is_empty() { return Err(argument::Error::InvalidValue { value: value.to_owned(), - expected: "`plugin-gid-map` must have exactly 3 components: <inner>:<outer>:<count>", + expected: + "`plugin-gid-map` must have exactly 3 components: <inner>[:[<outer>][:<count>]]", }); } @@ -325,19 +330,21 @@ fn parse_plugin_gid_map_option(value: &str) -> argument::Result<GidMap> { expected: "the <inner> component for `plugin-gid-map` is not valid gid", })?; - let outer: libc::gid_t = components[1] - .parse() - .map_err(|_| argument::Error::InvalidValue { + let outer: libc::gid_t = match components.get(1) { + None | Some(&"") => inner, + Some(s) => s.parse().map_err(|_| argument::Error::InvalidValue { value: components[1].to_owned(), expected: "the <outer> component for `plugin-gid-map` is not valid gid", - })?; + })?, + }; - let count: u32 = components[2] - .parse() - .map_err(|_| argument::Error::InvalidValue { + let count: u32 = match components.get(2) { + None => 1, + Some(s) => s.parse().map_err(|_| argument::Error::InvalidValue { value: components[2].to_owned(), expected: "the <count> component for `plugin-gid-map` is not valid number", - })?; + })?, + }; Ok(GidMap { inner, @@ -1672,4 +1679,92 @@ mod tests { set_argument(&mut config, "serial", Some("num=2,type=stdout,stdin=true")) .expect_err("should fail to parse a second serial port connected to stdin"); } + + #[test] + fn parse_plugin_mount_valid() { + let mut config = Config::default(); + set_argument( + &mut config, + "plugin-mount", + Some("/dev/null:/dev/zero:true"), + ) + .expect("parse should succeed"); + assert_eq!(config.plugin_mounts[0].src, PathBuf::from("/dev/null")); + assert_eq!(config.plugin_mounts[0].dst, PathBuf::from("/dev/zero")); + assert_eq!(config.plugin_mounts[0].writable, true); + } + + #[test] + fn parse_plugin_mount_valid_shorthand() { + let mut config = Config::default(); + set_argument(&mut config, "plugin-mount", Some("/dev/null")).expect("parse should succeed"); + assert_eq!(config.plugin_mounts[0].dst, PathBuf::from("/dev/null")); + assert_eq!(config.plugin_mounts[0].writable, false); + set_argument(&mut config, "plugin-mount", Some("/dev/null:/dev/zero")) + .expect("parse should succeed"); + assert_eq!(config.plugin_mounts[1].dst, PathBuf::from("/dev/zero")); + assert_eq!(config.plugin_mounts[1].writable, false); + set_argument(&mut config, "plugin-mount", Some("/dev/null::true")) + .expect("parse should succeed"); + assert_eq!(config.plugin_mounts[2].dst, PathBuf::from("/dev/null")); + assert_eq!(config.plugin_mounts[2].writable, true); + } + + #[test] + fn parse_plugin_mount_invalid() { + let mut config = Config::default(); + set_argument(&mut config, "plugin-mount", Some("")).expect_err("parse should fail"); + set_argument( + &mut config, + "plugin-mount", + Some("/dev/null:/dev/null:true:false"), + ) + .expect_err("parse should fail because too many arguments"); + set_argument(&mut config, "plugin-mount", Some("null:/dev/null:true")) + .expect_err("parse should fail because source is not absolute"); + set_argument(&mut config, "plugin-mount", Some("/dev/null:null:true")) + .expect_err("parse should fail because source is not absolute"); + set_argument(&mut config, "plugin-mount", Some("/dev/null:null:blah")) + .expect_err("parse should fail because flag is not boolean"); + } + + #[test] + fn parse_plugin_gid_map_valid() { + let mut config = Config::default(); + set_argument(&mut config, "plugin-gid-map", Some("1:2:3")).expect("parse should succeed"); + assert_eq!(config.plugin_gid_maps[0].inner, 1); + assert_eq!(config.plugin_gid_maps[0].outer, 2); + assert_eq!(config.plugin_gid_maps[0].count, 3); + } + + #[test] + fn parse_plugin_gid_map_valid_shorthand() { + let mut config = Config::default(); + set_argument(&mut config, "plugin-gid-map", Some("1")).expect("parse should succeed"); + assert_eq!(config.plugin_gid_maps[0].inner, 1); + assert_eq!(config.plugin_gid_maps[0].outer, 1); + assert_eq!(config.plugin_gid_maps[0].count, 1); + set_argument(&mut config, "plugin-gid-map", Some("1:2")).expect("parse should succeed"); + assert_eq!(config.plugin_gid_maps[1].inner, 1); + assert_eq!(config.plugin_gid_maps[1].outer, 2); + assert_eq!(config.plugin_gid_maps[1].count, 1); + set_argument(&mut config, "plugin-gid-map", Some("1::3")).expect("parse should succeed"); + assert_eq!(config.plugin_gid_maps[2].inner, 1); + assert_eq!(config.plugin_gid_maps[2].outer, 1); + assert_eq!(config.plugin_gid_maps[2].count, 3); + } + + #[test] + fn parse_plugin_gid_map_invalid() { + let mut config = Config::default(); + set_argument(&mut config, "plugin-gid-map", Some("")).expect_err("parse should fail"); + set_argument(&mut config, "plugin-gid-map", Some("1:2:3:4")) + .expect_err("parse should fail because too many arguments"); + set_argument(&mut config, "plugin-gid-map", Some("blah:2:3")) + .expect_err("parse should fail because inner is not a number"); + set_argument(&mut config, "plugin-gid-map", Some("1:blah:3")) + .expect_err("parse should fail because outer is not a number"); + set_argument(&mut config, "plugin-gid-map", Some("1:2:blah")) + .expect_err("parse should fail because count is not a number"); + } } |