From: Ian Jackson Date: Tue, 22 Dec 2020 22:32:23 +0000 (+0000) Subject: wip tmpdir setup X-Git-Tag: otter-0.2.0~170 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=fd44fd90b82350691422ade434fbc23261dfd89e;p=otter.git wip tmpdir setup Signed-off-by: Ian Jackson --- diff --git a/Cargo.lock.example b/Cargo.lock.example index 1420f23a..b388ddd5 100644 --- a/Cargo.lock.example +++ b/Cargo.lock.example @@ -1536,6 +1536,7 @@ dependencies = [ "fehler", "structopt", "thirtyfour_sync", + "void", ] [[package]] @@ -2895,6 +2896,12 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "walkdir" version = "2.3.1" diff --git a/wdriver.rs b/wdriver.rs index 138c9ec0..40ba3955 100644 --- a/wdriver.rs +++ b/wdriver.rs @@ -2,12 +2,124 @@ // SPDX-License-Identifier: AGPL-3.0-or-later // There is NO WARRANTY. -pub use fehler::throws; +pub use anyhow::{anyhow, Context}; +pub use fehler::{throw, throws}; pub use structopt::StructOpt; +pub use void::Void; pub use std::env; -pub use std::io::Write; +pub use std::fs; +pub use std::io::{ErrorKind, Write}; pub use std::os::unix::process::CommandExt; +pub use std::os::unix::fs::DirBuilderExt; +pub use std::os::linux::fs::MetadataExt; // todo why linux for st_mode?? pub use std::process::Command; pub type AE = anyhow::Error; + + +#[derive(Debug,Clone)] +#[derive(StructOpt)] +struct Opts { + #[structopt(long="--no-bwrap")] + no_bwrap: bool, + + #[structopt(long="--tmp-dir", default_value="tmp")] + tmp_dir: String, +} + +#[derive(Debug,Clone)] +pub struct Setup { + tmp: String, +} + +#[throws(AE)] +fn reinvoke_via_bwrap(_opts: &Opts, current_exe: &str) -> Void { + println!("running bwrap"); + + let mut bcmd = Command::new("bwrap"); + bcmd.args("--unshare-net \ + --dev-bind / / \ + --tmpfs /tmp \ + --die-with-parent".split(" ")) + .arg(current_exe) + .arg("--no-bwrap") + .args(env::args_os().skip(1)); + + std::io::stdout().flush().context("flush stdout")?; + let e : AE = bcmd.exec().into(); + throw!(e.context("exec bwrap")); +} + +#[throws(AE)] +fn prepare_tmpdir(opts: &Opts, current_exe: &str) -> String { + (||{ + match fs::metadata(&opts.tmp_dir) { + Ok(m) => { + if !m.is_dir() { + throw!(anyhow!("existing object is not a directory")); + } + if (m.st_mode() & 0o0102) != 0 { + throw!(anyhow!( + "existing directory mode {:#o} is sticky or world-writeable. \ + We use predictable pathnames so that would be a tmp race", + m.st_mode() + )); + } + } + Err(e) if e.kind() == ErrorKind::NotFound => { + fs::create_dir(&opts.tmp_dir) + .context("create")?; + } + Err(e) => { + let e : AE = e.into(); + throw!(e.context("stat existing directory")) + } + } + + env::set_current_dir(&opts.tmp_dir) + .context("chdir into it")?; + + Ok::<_,AE>(()) + })() + .with_context(|| opts.tmp_dir.to_owned()) + .context("prepare/create tmp-dir")?; + + let leaf = current_exe.rsplitn(1, '/').next().unwrap(); + let our_tmpdir = format!("{}/{}", &opts.tmp_dir, &leaf); + (||{ + match fs::remove_dir_all(&leaf) { + Ok(()) => {}, + Err(e) if e.kind() == ErrorKind::NotFound => {}, + Err(e) => throw!(AE::from(e).context("remove previous directory")), + }; + fs::DirBuilder::new().mode(0o700).create(&leaf) + .context("create fresh subdirectory")?; + Ok::<_,AE>(()) + })() + .with_context(|| our_tmpdir.to_owned()) + .context("prepare/create our tmp subdir")?; + + our_tmpdir +} + +#[throws(AE)] +pub fn setup() -> Setup { + let current_exe : String = env::current_exe() + .context("find current executable")? + .to_str() + .ok_or_else(|| anyhow!("current executable path is not UTF-8 !"))? + .to_owned(); + + let opts = Opts::from_args(); + if !opts.no_bwrap { + reinvoke_via_bwrap(&opts, ¤t_exe) + .context("reinvoke via bwrap")?; + } + + let tmp = prepare_tmpdir(&opts, ¤t_exe)?; + + Setup { + tmp, + } +} diff --git a/wdriver/Cargo.toml b/wdriver/Cargo.toml index 823b8a23..6b563799 100644 --- a/wdriver/Cargo.toml +++ b/wdriver/Cargo.toml @@ -15,6 +15,7 @@ anyhow = "1" fehler = "1" thirtyfour_sync = "0.21" structopt = "0.3" +void = "1" [lib] name = "otter_webdriver_tests" diff --git a/wdriver/simple.rs b/wdriver/simple.rs deleted file mode 100644 index 9f1fa8f7..00000000 --- a/wdriver/simple.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2020 Ian Jackson -// SPDX-License-Identifier: AGPL-3.0-or-later -// There is NO WARRANTY. - -use otter_webdriver_tests::*; - -#[derive(StructOpt)] -struct Opts { - #[structopt(long="--no-bwrap")] - no_bwrap: bool, -} - -#[throws(AE)] -fn main(){ - let opts = Opts::from_args(); - - if !opts.no_bwrap { - println!("running bwrap"); - - let mut bcmd = Command::new("bwrap"); - bcmd.args("--unshare-net \ - --dev-bind / / \ - --tmpfs /tmp \ - --die-with-parent".split(" ")) - .arg(env::current_exe().expect("failed to find current executable")) - .arg("--no-bwrap") - .args(env::args_os().skip(1)); - - std::io::stdout().flush().unwrap(); - Err(bcmd.exec()).unwrap() - } - - println!("hi!"); -} diff --git a/wdriver/wdt-simple.rs b/wdriver/wdt-simple.rs new file mode 100644 index 00000000..76eda428 --- /dev/null +++ b/wdriver/wdt-simple.rs @@ -0,0 +1,12 @@ +// Copyright 2020 Ian Jackson +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use otter_webdriver_tests::*; + +#[throws(AE)] +fn main(){ + let s = setup()?; + + println!("hi! {:#?}", &s); +}