-
Notifications
You must be signed in to change notification settings - Fork 217
Expand file tree
/
Copy pathcli_internals.rs
More file actions
108 lines (94 loc) · 2.92 KB
/
Copy pathcli_internals.rs
File metadata and controls
108 lines (94 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::{
io::{BufRead as _, Seek},
os::fd::IntoRawFd,
};
use anyhow::{Context as _, Result};
use cap_std::fs::Dir;
use cap_std_ext::cap_tempfile;
use clap::Parser;
use ostree_ext::gio;
use crate::{bwrap, ffi::BubblewrapMutability, impl_sealed_memfd};
#[derive(Debug, Parser)]
#[clap(rename_all = "kebab-case")]
/// Main options struct
struct Internals {
#[clap(subcommand)]
cmd: Cmd,
}
#[derive(Debug, Parser)]
#[clap(rename_all = "kebab-case")]
/// Options for invoking bubblewrap
struct BwrapOpts {
/// Path to rootfs
root: String,
/// Arguments
args: Vec<String>,
}
#[derive(Debug, Parser)]
#[clap(rename_all = "kebab-case")]
/// Options for invoking bubblewrap
struct BwrapScriptOpts {
/// Path to rootfs
root: String,
/// Path to interpeter
interp: String,
/// Path to script
script: String,
}
#[derive(Debug, clap::Subcommand)]
#[clap(rename_all = "kebab-case")]
/// Subcommands
enum Cmd {
/// Invoke bubblewrap
Bwrap(BwrapOpts),
/// Invoke bubblewrap the same way rpm-ostree does for scripts.
BwrapScript(BwrapScriptOpts),
}
impl BwrapOpts {
fn run(self) -> Result<()> {
let root = &Dir::open_ambient_dir(&self.root, cap_std::ambient_authority())?;
let mut bwrap =
bwrap::Bubblewrap::new_with_mutability(root, BubblewrapMutability::MutateFreely)?;
bwrap.append_child_argv(self.args.iter().map(|s| s.as_str()));
bwrap.run_inner(gio::Cancellable::NONE)?;
Ok(())
}
}
impl BwrapScriptOpts {
fn run(self) -> Result<()> {
let authority = cap_std::ambient_authority();
let root = &Dir::open_ambient_dir(&self.root, authority)?;
let mut bwrap =
bwrap::Bubblewrap::new_with_mutability(root, BubblewrapMutability::MutateFreely)?;
let td = Dir::open_ambient_dir("/var/tmp", authority)?;
let mut output = cap_tempfile::TempFile::new_anonymous(&td)?.into_std();
bwrap.append_child_arg(&self.interp);
bwrap.take_stdout_and_stderr_fd(output.try_clone()?.into_raw_fd());
let script = std::fs::read_to_string(self.script)?;
let mfd = impl_sealed_memfd("script", script.as_bytes())?;
bwrap.take_fd(mfd.into_raw_fd(), 5);
bwrap.append_child_arg("/proc/self/fd/5");
bwrap.run_inner(gio::Cancellable::NONE)?;
output.seek(std::io::SeekFrom::Start(0))?;
let output = std::io::BufReader::new(output);
for line in output.lines() {
let line = line.context("Reading line")?;
println!("script: {line}");
}
Ok(())
}
}
impl Cmd {
fn run(self) -> Result<()> {
match self {
Cmd::Bwrap(args) => args.run(),
Cmd::BwrapScript(args) => args.run(),
}
}
}
pub fn main(argv: &[&str]) -> Result<i32> {
let opt = Internals::parse_from(argv.into_iter().skip(1));
opt.cmd.run()?;
Ok(0)
}