use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
const ADVANCED_BINARY_FILTER_FILE_NAME: &str = "seccomp_filter.bpf";
const BASIC_BINARY_FILTER_FILE_NAME: &str = "basic_seccomp_filter.bpf";
const JSON_DIR: &str = "../../resources/seccomp";
const SECCOMPILER_BUILD_DIR: &str = "../../build/seccompiler";
const SECCOMPILER_SRC_DIR: &str = "../seccompiler/src";
fn main() {
let target = env::var("TARGET").expect("Missing target.");
let out_dir = env::var("OUT_DIR").expect("Missing build-level OUT_DIR.");
let mut json_path = PathBuf::from(JSON_DIR);
json_path.push(format!("{}.json", target));
if !json_path.exists() {
json_path.pop();
json_path.push("unimplemented.json");
println!(
"cargo:warning=No default seccomp policy for target: {}. \
Defaulting to `resources/seccomp/unimplemented.json`.",
target
);
}
let json_path = json_path.to_str().expect("Invalid bytes");
println!("cargo:rerun-if-changed={}", json_path);
register_seccompiler_src_watchlist(Path::new(SECCOMPILER_SRC_DIR));
let mut bpf_out_path = PathBuf::from(&out_dir);
bpf_out_path.push(ADVANCED_BINARY_FILTER_FILE_NAME);
run_seccompiler_bin(
&target,
json_path,
bpf_out_path.to_str().expect("Invalid bytes."),
false,
);
let mut bpf_out_path = PathBuf::from(&out_dir);
bpf_out_path.push(BASIC_BINARY_FILTER_FILE_NAME);
run_seccompiler_bin(
&target,
json_path,
bpf_out_path.to_str().expect("Invalid bytes."),
true,
);
}
fn run_seccompiler_bin(cargo_target: &str, json_path: &str, out_path: &str, basic: bool) {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("Missing target arch.");
let mut command = Command::new("cargo");
command.args(&[
"run",
"-p",
"seccompiler",
"--verbose",
"--target",
&cargo_target,
"--target-dir",
SECCOMPILER_BUILD_DIR,
"--",
"--input-file",
&json_path,
"--target-arch",
&target_arch,
"--output-file",
out_path,
]);
if basic {
command.arg("--basic");
}
match command.output() {
Err(error) => panic!("\nSeccompiler-bin error: {:?}\n", error),
Ok(result) if !result.status.success() => {
panic!(
"\nSeccompiler-bin returned non-zero exit code:\nstderr: {}\nstdout: {}\n",
String::from_utf8(result.stderr).unwrap(),
String::from_utf8(result.stdout).unwrap(),
);
}
Ok(_) => {}
}
}
fn register_seccompiler_src_watchlist(src_dir: &Path) {
let contents = fs::read_dir(src_dir).expect("Unable to read folder contents.");
for entry in contents {
let path = entry.unwrap().path();
let metadata = fs::metadata(&path).expect("Unable to read file/folder metadata.");
if metadata.is_file() {
println!(
"cargo:rerun-if-changed={}",
path.to_str().expect("Invalid unicode bytes.")
);
} else if metadata.is_dir() {
register_seccompiler_src_watchlist(&path);
}
}
}