Skip to content

Commit 67fc211

Browse files
committed
feat: handle hermit images + config nested in image
1 parent e1dbf83 commit 67fc211

File tree

24 files changed

+1148
-106
lines changed

24 files changed

+1148
-106
lines changed

Cargo.lock

Lines changed: 153 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[workspace]
2+
members = ["hermit-image-reader", "uhyve-interface"]
23
exclude = ["tests/test-kernels", "hermit-rs", "hermit-rs/*", "kernel"]
34

45
[package]
@@ -51,6 +52,7 @@ env_logger = "0.11"
5152
gdbstub = "0.7"
5253
gdbstub_arch = "0.3"
5354
hermit-entry = { version = "0.10.5", features = ["loader"] }
55+
hermit-image-reader = { version = "0.1", path = "hermit-image-reader" }
5456
libc = "0.2"
5557
log = "0.4"
5658
mac_address = "1.1"

hermit-image-reader/Cargo.toml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[package]
2+
name = "hermit-image-reader"
3+
version = "0.1.0"
4+
edition = "2024"
5+
license = "MIT OR Apache-2.0"
6+
7+
[features]
8+
std = ["compression/std"]
9+
10+
[dependencies]
11+
12+
[dependencies.byte-unit]
13+
version = "5"
14+
default-features = false
15+
features = ["byte", "serde"]
16+
17+
[dependencies.compression]
18+
version = "0.1"
19+
default-features = false
20+
features = ["gzip"]
21+
22+
[dependencies.num-traits]
23+
version = "0.2"
24+
default-features = false
25+
26+
[dependencies.serde]
27+
version = "1"
28+
default-features = false
29+
features = ["alloc", "derive"]
30+
31+
[dependencies.toml]
32+
version = "0.9"
33+
default-features = false
34+
features = ["parse", "serde"]
35+
36+
[dependencies.yoke]
37+
version = "0.8"
38+
default-features = false
39+
features = ["derive"]
40+
41+
[dev-dependencies]
42+
proptest = "1.9.0"

hermit-image-reader/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-APACHE

hermit-image-reader/LICENSE-MIT

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE-MIT

hermit-image-reader/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# hermit-image-reader
2+
3+
This Rust crate implements a basic reader for Hermit images.
4+
Overall, these are just `.tar.gz` (i.e. gzipped tar) files.
5+
6+
For performance reasons, it should be preferred to put the config and kernel
7+
as the first two entries of the image (tar files don't have any sorting or index,
8+
except that normally, the latest entry of the file takes precedence).
9+
If this condition is not adhered to, some hermit / uhyve tools might refuse
10+
to work with the image, or emit a warning.
11+
12+
They contain at least 2 special entries:
13+
* The config file (in TOML format), at `hermit_config.toml` in the image root.
14+
The expected entries are described in the crate documentation in `hermit_image_reader::config::Config`.
15+
* A Hermit Kernel ELF file, whose path is specified in the config.
16+
17+
The image itself is mapped (from the Hermit kernel perspective) into a path
18+
(`mount_point`) specified in the config file.
19+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
fn main() {
2+
for f in std::env::args().skip(1) {
3+
println!("# File {}:", f);
4+
let data = std::fs::read(f).expect("unable to read image file");
5+
let decompressed = hermit_image_reader::decompress_image(&data[..])
6+
.expect("unable to decompress image file");
7+
for i in hermit_image_reader::ImageParser::new(&decompressed[..]) {
8+
let i = i.expect("unable to read image entry");
9+
print!(" Entry ");
10+
let maybe_name = i.name.try_as_str();
11+
if let Some(name) = maybe_name {
12+
print!("{:?}", name);
13+
} else {
14+
print!("{:?}", i.name);
15+
}
16+
if i.is_exec {
17+
print!(" (executable)");
18+
}
19+
print!(" :: {:?} :: starts with: ", i.value_range);
20+
let value_start = &i.value[..core::cmp::min(20, i.value.len())];
21+
22+
if let Ok(value_start) = str::from_utf8(value_start) {
23+
println!("{:?}", value_start);
24+
} else {
25+
println!("{:?}", value_start);
26+
}
27+
28+
if let Some(name) = maybe_name {
29+
if name
30+
== hermit_image_reader::StrFilename::One(
31+
hermit_image_reader::config::DEFAULT_CONFIG_NAME,
32+
) {
33+
match hermit_image_reader::config::parse(i.value) {
34+
Ok(config) => println!("parsed config ::\n{:#?}\n", config),
35+
Err(e) => eprintln!("failed to parse config :: {}", e),
36+
}
37+
}
38+
}
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)