chiark / gitweb /
wip tmpdir setup
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 22 Dec 2020 22:32:23 +0000 (22:32 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 22 Dec 2020 22:32:23 +0000 (22:32 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Cargo.lock.example
wdriver.rs
wdriver/Cargo.toml
wdriver/simple.rs [deleted file]
wdriver/wdt-simple.rs [new file with mode: 0644]

index 1420f23a2eb1b63c76f04bc117265dbaa4e1b2ea..b388ddd528b84e02f4b459def0d21cfc888b5c20 100644 (file)
@@ -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"
index 138c9ec0f56afa1c725b343a85fc98f5c1cc3868..40ba395514c5773d1dfff27692c8eda8c8f676e5 100644 (file)
 // 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, &current_exe)
+      .context("reinvoke via bwrap")?;
+  }
+
+  let tmp = prepare_tmpdir(&opts, &current_exe)?;
+
+  Setup {
+    tmp,
+  }
+}
index 823b8a235fc7560262bebc47914efcde4a89dc56..6b5637999d25a80a5578450fd537f5ed1064d733 100644 (file)
@@ -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 (file)
index 9f1fa8f..0000000
+++ /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 (file)
index 0000000..76eda42
--- /dev/null
@@ -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);
+}