From 4a63f9c396011f173a29581c96315b490de81e80 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Mon, 9 Mar 2026 12:12:51 -0400 Subject: [PATCH 1/9] deps: Upgrade cap-std-ext from 4.x to 5.0 Align cap-std-ext with the version used by bootc-internal-blockdev, eliminating duplicate cap-std/cap-primitives dependency chains. Assisted-by: Claude Code (Opus 4) Signed-off-by: ckyrouac --- Cargo.lock | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index dc2662a0..1011f8b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,7 @@ dependencies = [ "anyhow", "bootc-internal-utils", "camino", + "cap-std-ext", "fn-error-context", "libc", "regex", @@ -180,6 +181,44 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "bootc-internal-utils" +version = "0.1.0" +source = "git+https://github.com/bootc-dev/bootc#df3e863fec17ea35ea5e12e4a21b323662d54a27" +dependencies = [ + "anstream 1.0.0", + "anyhow", + "cap-std-ext", + "chrono", + "owo-colors", + "rustix 1.1.3", + "serde", + "serde_json", + "shlex", + "tempfile", + "tokio", + "tracing", + "tracing-journald", + "tracing-subscriber", +] + +[[package]] +name = "bootc-mount" +version = "0.0.0" +source = "git+https://github.com/bootc-dev/bootc#df3e863fec17ea35ea5e12e4a21b323662d54a27" +dependencies = [ + "anyhow", + "bootc-internal-utils 0.1.0 (git+https://github.com/bootc-dev/bootc)", + "camino", + "cap-std-ext", + "fn-error-context", + "libc", + "rustix 1.1.3", + "serde", + "tempfile", + "tracing", +] + [[package]] name = "bootupd" version = "0.2.32" @@ -266,6 +305,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7281235d6e96d3544ca18bba9049be92f4190f8d923e3caef1b5f66cfa752608" dependencies = [ + "camino", "cap-primitives", "io-extras", "io-lifetimes 3.0.1", @@ -290,6 +330,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f22d5c0b1147e8bd9105fa004450f673c139d7e632f7edc3980f94a51f20f3" dependencies = [ + "camino", "cap-std", "rand 0.9.2", "rustix 1.1.4", From 17c5ade438f82261c8ce510d206f713bd77aabcc Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Tue, 10 Mar 2026 10:54:57 -0400 Subject: [PATCH 2/9] deps: Update blockdev crate Signed-off-by: ckyrouac --- Cargo.lock | 972 ++++++++++++++++++++++++++++++++--------------------- Cargo.toml | 2 +- 2 files changed, 588 insertions(+), 386 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1011f8b6..3be9a944 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,26 +2,11 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -43,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -58,37 +43,37 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", - "once_cell", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] @@ -99,24 +84,9 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" @@ -126,9 +96,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "block-buffer" @@ -141,18 +111,18 @@ dependencies = [ [[package]] name = "bootc-internal-blockdev" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3136c26ac5666414667ea27e3383ec7de265e20ff2ca5f61ae38c6e0c96345fb" +checksum = "54393bf69cc17ef659609f3b1143beed0f7529c79ef045a876621a2f946a0051" dependencies = [ "anyhow", + "bootc-internal-mount", "bootc-internal-utils", "camino", "cap-std-ext", "fn-error-context", "libc", - "regex", - "rustix 1.1.4", + "rustix", "serde", "serde_json", "tempfile", @@ -161,37 +131,34 @@ dependencies = [ ] [[package]] -name = "bootc-internal-utils" +name = "bootc-internal-mount" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3292185c166091432ecbc6b203c0c73953d6b5965908368c51df800f1c549ed" +checksum = "2112a3bed0dd0ce551b7505fae6e7b57609952c666c3345d85ac289f3b396276" dependencies = [ - "anstream", "anyhow", - "chrono", - "owo-colors", - "rustix 1.1.4", + "bootc-internal-utils", + "camino", + "cap-std-ext", + "fn-error-context", + "libc", + "rustix", "serde", - "serde_json", - "shlex", "tempfile", - "tokio", "tracing", - "tracing-journald", - "tracing-subscriber", ] [[package]] name = "bootc-internal-utils" version = "0.1.0" -source = "git+https://github.com/bootc-dev/bootc#df3e863fec17ea35ea5e12e4a21b323662d54a27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3292185c166091432ecbc6b203c0c73953d6b5965908368c51df800f1c549ed" dependencies = [ - "anstream 1.0.0", + "anstream", "anyhow", - "cap-std-ext", "chrono", "owo-colors", - "rustix 1.1.3", + "rustix", "serde", "serde_json", "shlex", @@ -202,23 +169,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "bootc-mount" -version = "0.0.0" -source = "git+https://github.com/bootc-dev/bootc#df3e863fec17ea35ea5e12e4a21b323662d54a27" -dependencies = [ - "anyhow", - "bootc-internal-utils 0.1.0 (git+https://github.com/bootc-dev/bootc)", - "camino", - "cap-std-ext", - "fn-error-context", - "libc", - "rustix 1.1.3", - "serde", - "tempfile", - "tracing", -] - [[package]] name = "bootupd" version = "0.2.32" @@ -244,7 +194,7 @@ dependencies = [ "os-release", "regex", "rpm", - "rustix 1.1.4", + "rustix", "serde", "serde_json", "signal-hook-registry", @@ -256,21 +206,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytes" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "camino" @@ -293,9 +237,9 @@ dependencies = [ "io-lifetimes 3.0.1", "ipnet", "maybe-owned", - "rustix 1.1.4", + "rustix", "rustix-linux-procfs", - "windows-sys 0.61.1", + "windows-sys 0.61.2", "winx", ] @@ -309,19 +253,19 @@ dependencies = [ "cap-primitives", "io-extras", "io-lifetimes 3.0.1", - "rustix 1.1.4", + "rustix", ] [[package]] name = "cap-std-ext" -version = "5.0.0" +version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d201b8b353bc963f2e8c374be7866dba47082ff041fb0db2d7543f2b9c8367ce" +checksum = "56f9d7cf114dea582f663f03f4c563d0fc5ca2c8fa4c496eb538d8f01981ea51" dependencies = [ "cap-primitives", "cap-tempfile", "libc", - "rustix 1.1.4", + "rustix", ] [[package]] @@ -333,26 +277,27 @@ dependencies = [ "camino", "cap-std", "rand 0.9.2", - "rustix 1.1.4", + "rustix", "rustix-linux-procfs", "uuid", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] name = "cc" -version = "1.2.13" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -376,9 +321,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -386,9 +331,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstyle", "clap_lex", @@ -397,27 +342,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "core-foundation-sys" @@ -442,9 +387,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -486,7 +431,7 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" dependencies = [ "num-traits", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] @@ -512,14 +457,20 @@ dependencies = [ "log", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -539,6 +490,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "fn-error-context" version = "0.2.1" @@ -547,9 +504,15 @@ checksum = "2cd66269887534af4b0c3e3337404591daa8dc8b9b2b3db71f9523beb4bafb41" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -567,12 +530,12 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fs-set-times" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2e6123af26f0f2c51cc66869137080199406754903cc926a7690401ce09cb4" +checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes 2.0.4", - "rustix 0.38.44", + "rustix", "windows-sys 0.59.0", ] @@ -598,32 +561,54 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", + "r-efi 5.3.0", + "wasip2", ] [[package]] -name = "gimli" -version = "0.31.1" +name = "getrandom" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -648,14 +633,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -669,6 +655,24 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + [[package]] name = "io-extras" version = "0.19.0" @@ -676,7 +680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20fd6de4ccfcc187e38bc21cfa543cb5a302cb86a8b114eb7f0bf0dc9f8ac00f" dependencies = [ "io-lifetimes 3.0.1", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -693,15 +697,15 @@ checksum = "2f0fb0570afe1fed943c5c3d4102d5358592d8625fda6a0007fdbe65a92fba96" [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -714,39 +718,39 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.4" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.4" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -758,11 +762,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.182" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libsystemd" @@ -782,12 +792,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -802,11 +806,11 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -827,9 +831,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" @@ -855,24 +859,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -894,7 +889,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -922,12 +917,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -971,7 +965,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] @@ -1015,19 +1009,16 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.7" +name = "once_cell" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] -name = "once_cell" -version = "1.20.3" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openat" @@ -1052,11 +1043,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -1073,14 +1064,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -1097,72 +1088,88 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -1210,7 +1217,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", ] [[package]] @@ -1219,7 +1226,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.4", ] [[package]] @@ -1230,41 +1237,26 @@ checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.12", - "regex-syntax 0.8.5", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722166aa0d7438abbaa4d5cc2c649dac844e8c56d82fb3d33e9c34b5cd268fc6" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rpm" @@ -1272,7 +1264,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "422ffe5b31ea4c7c76a361dc29b986e11fb6987313453088e1fd95f34ecc1ba6" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.11.0", "cpio", "digest", "enum-display-derive", @@ -1290,36 +1282,17 @@ dependencies = [ "thiserror", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.8.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.12.1", - "windows-sys 0.61.1", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1329,14 +1302,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.1.4", + "rustix", ] [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "same-file" @@ -1347,6 +1320,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -1374,7 +1353,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] @@ -1403,9 +1382,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -1439,9 +1418,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "strsim" @@ -1468,9 +1447,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1479,79 +1458,77 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.26.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.1", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.4", - "windows-sys 0.61.1", + "rustix", + "windows-sys 0.61.2", ] [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "tokio" -version = "1.43.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ - "backtrace", "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -1560,20 +1537,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -1603,14 +1580,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -1621,9 +1598,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uapi-version" @@ -1633,9 +1610,15 @@ checksum = "849f6b1fe8a0fb07170737d7f3acf72cac5462fb3f4e86614474a49f7fac3b65" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" @@ -1645,12 +1628,14 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.13.1" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.3.1", - "serde", + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] @@ -1683,50 +1668,46 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.98", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1734,26 +1715,60 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.98", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "widestring" version = "1.2.1" @@ -1778,11 +1793,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1793,26 +1808,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "windows-targets", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets", + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", ] [[package]] @@ -1821,14 +1871,23 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] @@ -1839,14 +1898,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -1855,90 +1931,216 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winx" version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.11.0", "windows-sys 0.59.0", ] [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "bitflags 2.8.0", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.117", ] [[package]] name = "zmij" -version = "1.0.12" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index bf29f05f..8f64a2ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ path = "src/main.rs" [dependencies] anyhow = "1.0" -bootc-internal-blockdev = "0.1.0" +bootc-internal-blockdev = "0.2.0" bootc-internal-utils = "0.1.0" cap-std-ext = "5.0.0" camino = "1.2.2" From 6380a4f083239aecdac45bead51fbbf214729577 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 4 Mar 2026 13:34:23 -0500 Subject: [PATCH 3/9] component: Clearer docs for Component trait Signed-off-by: ckyrouac --- src/component.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/component.rs b/src/component.rs index dca3c3bc..5d0ee0c8 100644 --- a/src/component.rs +++ b/src/component.rs @@ -20,7 +20,11 @@ pub(crate) enum ValidationResult { Errors(Vec), } -/// A component along with a possible update +/// A bootloader subsystem (EFI or BIOS) that can be installed, updated, and validated. +/// +/// Components encapsulate platform-specific bootloader management. Each implementation +/// handles installing bootloader files during image builds, applying updates at runtime, +/// and optionally adopting existing installations not originally managed by bootupd. pub(crate) trait Component { /// Returns the name of the component; this will be used for serialization /// and should remain stable. From 4d615798b8b3e45643e6edd2f46e62d1d6b0cf17 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 4 Mar 2026 13:29:02 -0500 Subject: [PATCH 4/9] blockdev: Remove blockdev code, it is now in the blockdev crate Signed-off-by: ckyrouac --- src/blockdev.rs | 137 ------------------------------------------------ src/main.rs | 1 - 2 files changed, 138 deletions(-) delete mode 100644 src/blockdev.rs diff --git a/src/blockdev.rs b/src/blockdev.rs deleted file mode 100644 index 9a1b9d74..00000000 --- a/src/blockdev.rs +++ /dev/null @@ -1,137 +0,0 @@ -use camino::{Utf8Path, Utf8PathBuf}; -use std::path::Path; - -use anyhow::{Context, Result}; -use bootc_internal_blockdev::PartitionTable; -use fn_error_context::context; - -#[context("get parent devices from mount point boot or sysroot")] -pub fn get_devices>(target_root: P) -> Result> { - let target_root = target_root.as_ref(); - let mut source = None; - - for path in ["boot", "sysroot"] { - let target_path = target_root.join(path); - if !target_path.exists() { - continue; - } - - let target_dir = openat::Dir::open(&target_path) - .with_context(|| format!("Opening {}", target_path.display()))?; - if let Ok(fsinfo) = crate::filesystem::inspect_filesystem(&target_dir, ".") { - source = Some(fsinfo.source); - break; - } - } - - let source = match source { - Some(s) => s, - None => anyhow::bail!("Failed to inspect filesystem from boot or sysroot"), - }; - - // Find the parent devices of the source path - let parent_devices = bootc_internal_blockdev::find_parent_devices(&source) - .with_context(|| format!("While looking for backing devices of {}", source))?; - log::debug!("Found parent devices: {parent_devices:?}"); - Ok(parent_devices) -} - -/// Find esp partition on the same device -/// using sfdisk to get partitiontable -pub fn get_esp_partition(device: &str) -> Result> { - let device_info: PartitionTable = - bootc_internal_blockdev::partitions_of(Utf8Path::new(device))?; - let esp = device_info.find_partition_of_esp()?; - Ok(esp.map(|v| v.node.clone())) -} - -/// Find all ESP partitions on the devices -pub fn find_colocated_esps(devices: &Vec) -> Result>> { - // look for all ESPs on those devices - let mut esps = Vec::new(); - for device in devices { - if let Some(esp) = get_esp_partition(&device)? { - esps.push(esp) - } - } - if esps.is_empty() { - return Ok(None); - } - log::debug!("Found esp partitions: {esps:?}"); - Ok(Some(esps)) -} - -/// Find bios_boot partition on the same device -#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] -pub fn get_bios_boot_partition(device: &str) -> Result> { - const BIOS_BOOT_TYPE_GUID: &str = "21686148-6449-6E6F-744E-656564454649"; - let device_info = bootc_internal_blockdev::partitions_of(Utf8Path::new(device))?; - let bios_boot = device_info - .partitions - .into_iter() - .find(|p| p.parttype.as_str() == BIOS_BOOT_TYPE_GUID); - if let Some(bios_boot) = bios_boot { - return Ok(Some(bios_boot.node)); - } - Ok(None) -} - -/// Find all bios_boot partitions on the devices -#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] -pub fn find_colocated_bios_boot(devices: &Vec) -> Result>> { - // look for all bios_boot parts on those devices - let mut bios_boots = Vec::new(); - for device in devices { - if let Some(bios) = get_bios_boot_partition(&device)? { - bios_boots.push(bios) - } - } - if bios_boots.is_empty() { - return Ok(None); - } - log::debug!("Found bios_boot partitions: {bios_boots:?}"); - Ok(Some(bios_boots)) -} - -// Check if the device is mpath -fn is_mpath(device: &str) -> Result { - let dm_path = Utf8PathBuf::from_path_buf(std::fs::canonicalize(device)?) - .map_err(|_| anyhow::anyhow!("Non-UTF8 path"))?; - let dm_name = dm_path.file_name().unwrap_or(""); - let uuid_path = Utf8PathBuf::from(format!("/sys/class/block/{dm_name}/dm/uuid")); - - if uuid_path.exists() { - let uuid = std::fs::read_to_string(&uuid_path) - .with_context(|| format!("Failed to read {uuid_path}"))?; - if uuid.trim_start().starts_with("mpath-") { - return Ok(true); - } - } - Ok(false) -} - -/// Get esp partition number from device -pub fn get_esp_partition_number(device: &str) -> Result { - let esp_device = - get_esp_partition(device)?.ok_or_else(|| anyhow::anyhow!("Failed to find ESP device"))?; - - let devname = esp_device - .rsplit_once('/') - .ok_or_else(|| anyhow::anyhow!("Failed to parse {esp_device}"))? - .1; - - let partition_path = Utf8PathBuf::from(format!("/sys/class/block/{devname}/partition")); - if partition_path.exists() { - return std::fs::read_to_string(&partition_path) - .with_context(|| format!("Failed to read {partition_path}")); - } - - // On multipath the partition attribute is not existing - if is_mpath(device)? { - if let Some(esp) = esp_device.strip_prefix(device) { - let esp_num = esp.trim_start_matches(|c: char| !c.is_ascii_digit()); - return Ok(esp_num.to_string()); - } - } - anyhow::bail!("Not supported for {device}") -} diff --git a/src/main.rs b/src/main.rs index 55543661..56e9ef99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,6 @@ Refs: mod backend; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] mod bios; -mod blockdev; mod bootupd; mod cli; mod component; From bacc54b64bb02c7e782bfa80e819de8ce7cbc501 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 4 Mar 2026 14:50:21 -0500 Subject: [PATCH 5/9] install: Migrate to using blockdev functions and Device Instead of referencing devices as a &str, use Device from the blockdev crate and its related functions. Signed-off-by: ckyrouac --- src/bios.rs | 13 +++++---- src/bootupd.rs | 24 +++++++++------- src/component.rs | 6 ++-- src/efi.rs | 75 +++++++++++++++++++++++++++++++----------------- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/bios.rs b/src/bios.rs index b6d11b6c..af4444d3 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -7,7 +7,8 @@ use std::io::prelude::*; use std::path::Path; use std::process::Command; -use crate::blockdev; +use bootc_internal_blockdev::Device; + use crate::bootupd::RootContext; use crate::component::*; use crate::freezethaw::fsfreeze_thaw_cycle; @@ -110,16 +111,18 @@ impl Component for Bios { &self, src_root: &str, dest_root: &str, - device: &str, + device: Option<&Device>, _update_firmware: bool, ) -> Result { + let device = + device.ok_or_else(|| anyhow::anyhow!("BIOS component requires a target device"))?; let src_dir = openat::Dir::open(src_root) .with_context(|| format!("opening source directory {src_root}"))?; let Some(meta) = get_component_update(&src_dir, self)? else { anyhow::bail!("No update metadata for component {} found", self.name()); }; - self.run_grub_install(dest_root, device)?; + self.run_grub_install(dest_root, &device.path())?; Ok(InstalledContent { meta, filetree: None, @@ -140,7 +143,7 @@ impl Component for Bios { Ok(Some(meta)) } - fn query_adopt(&self, devices: &Option>) -> Result> { + fn query_adopt(&self, devices: &Option>) -> Result> { #[cfg(target_arch = "x86_64")] if crate::efi::is_efi_booted()? && devices.is_none() { log::debug!("Skip BIOS adopt"); @@ -214,7 +217,7 @@ impl Component for Bios { update: &ContentMetadata, with_static_config: bool, ) -> Result> { - let bios_devices = blockdev::find_colocated_bios_boot(&rootcxt.devices)?; + let bios_devices = rootcxt.device.find_colocated_bios_boot()?; let Some(meta) = self.query_adopt(&bios_devices)? else { return Ok(None); }; diff --git a/src/bootupd.rs b/src/bootupd.rs index b7828691..98100266 100644 --- a/src/bootupd.rs +++ b/src/bootupd.rs @@ -31,6 +31,8 @@ use std::fs::{self, File}; use std::io::{BufRead, BufReader, BufWriter, Write}; use std::path::{Path, PathBuf}; +use bootc_internal_blockdev::Device; + pub(crate) enum ConfigMode { None, Static, @@ -50,15 +52,12 @@ impl ConfigMode { pub(crate) fn install( source_root: &str, dest_root: &str, - device: Option<&str>, + devices: &[Device], configs: ConfigMode, update_firmware: bool, target_components: Option<&[String]>, auto_components: bool, ) -> Result<()> { - // TODO: Change this to an Option<&str>; though this probably balloons into having - // DeviceComponent and FileBasedComponent - let device = device.unwrap_or(""); let source_root_dir = openat::Dir::open(source_root).context("Opening source root")?; SavedState::ensure_not_present(dest_root) .context("failed to install, invalid re-install attempted")?; @@ -90,8 +89,8 @@ pub(crate) fn install( let mut state = SavedState::default(); let mut installed_efi_vendor = None; for &component in target_components.iter() { - // skip for BIOS if device is empty - if component.name() == "BIOS" && device.is_empty() { + // skip for BIOS if no devices specified + if component.name() == "BIOS" && devices.is_empty() { println!( "Skip installing component {} without target device", component.name() @@ -518,15 +517,18 @@ pub(crate) fn print_status(status: &Status) -> Result<()> { pub struct RootContext { pub sysroot: openat::Dir, pub path: Utf8PathBuf, - pub devices: Vec, + + // The block device backing the root filesystem. + // This is used to determine the device to install to for components that need it, and also passed to component update/adoption logic which may need it for validation or other purposes. + pub device: Device, } impl RootContext { - fn new(sysroot: openat::Dir, path: &str, devices: Vec) -> Self { + fn new(sysroot: openat::Dir, path: &str, device: Device) -> Self { Self { sysroot, path: Utf8Path::new(path).into(), - devices, + device, } } } @@ -535,8 +537,8 @@ impl RootContext { fn prep_before_update() -> Result { let path = "/"; let sysroot = openat::Dir::open(path).context("Opening root dir")?; - let devices = crate::blockdev::get_devices(path).context("get parent devices")?; - Ok(RootContext::new(sysroot, path, devices)) + let device = bootc_internal_blockdev::list_dev(Utf8Path::new(path).into())?; + Ok(RootContext::new(sysroot, path, device)) } pub(crate) fn client_run_update() -> Result<()> { diff --git a/src/component.rs b/src/component.rs index 5d0ee0c8..edce556a 100644 --- a/src/component.rs +++ b/src/component.rs @@ -10,6 +10,8 @@ use openat_ext::OpenatDirExt; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; +use bootc_internal_blockdev::Device; + use crate::{bootupd::RootContext, model::*}; #[derive(Serialize, Deserialize, Debug)] @@ -33,7 +35,7 @@ pub(crate) trait Component { /// In an operating system whose initially booted disk image is not /// using bootupd, detect whether it looks like the component exists /// and "synthesize" content metadata from it. - fn query_adopt(&self, devices: &Option>) -> Result>; + fn query_adopt(&self, devices: &Option>) -> Result>; // Backup the current grub config, and install static grub config from tree fn migrate_static_grub_config(&self, sysroot_path: &str, destdir: &openat::Dir) -> Result<()>; @@ -57,7 +59,7 @@ pub(crate) trait Component { &self, src_root: &str, dest_root: &str, - device: &str, + device: Option<&Device>, update_firmware: bool, ) -> Result; diff --git a/src/efi.rs b/src/efi.rs index 2d437eef..5786a4c6 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -5,6 +5,7 @@ */ use std::cell::RefCell; +use std::os::unix::fs::MetadataExt; use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; use std::process::Command; @@ -23,13 +24,15 @@ use rustix::{fd::AsFd, fd::BorrowedFd, fs::StatVfsMountFlags}; use walkdir::WalkDir; use widestring::U16CString; +use bootc_internal_blockdev::Device; + use crate::bootupd::RootContext; use crate::freezethaw::fsfreeze_thaw_cycle; use crate::model::*; use crate::ostreeutil; use crate::util; -use crate::{blockdev, filetree, grubconfigs}; use crate::{component::*, packagesystem::*}; +use crate::{filetree, grubconfigs}; /// Well-known paths to the ESP that may have been mounted external to us. pub(crate) const ESP_MOUNTS: &[&str] = &["boot/efi", "efi", "boot"]; @@ -147,7 +150,12 @@ impl Efi { } #[context("Updating EFI firmware variables")] - fn update_firmware(&self, device: &str, espdir: &openat::Dir, vendordir: &str) -> Result<()> { + fn update_firmware( + &self, + device: &Device, + espdir: &openat::Dir, + vendordir: &str, + ) -> Result<()> { if !is_efi_booted()? { log::debug!("Not booted via EFI, skipping firmware update"); return Ok(()); @@ -177,11 +185,15 @@ impl Efi { log::debug!("Get product name: '{product_name}'"); assert!(product_name.len() > 0); - let esp_part_num = blockdev::get_esp_partition_number(device)?; + // Multi-device is handled by the caller: Efi::install() is called once + // per device in the loop at bootupd.rs install(), so each device's ESP + // gets its firmware updated individually. + let esp_part_num = device.get_esp_partition_number()?; // clear all the boot entries that match the target name clear_efi_target(&product_name)?; - create_efi_boot_entry(device, esp_part_num.trim(), &loader, &product_name) + let device_path = device.path(); + create_efi_boot_entry(&device_path, esp_part_num.trim(), &loader, &product_name) } } @@ -268,7 +280,7 @@ impl Component for Efi { "EFI" } - fn query_adopt(&self, devices: &Option>) -> Result> { + fn query_adopt(&self, devices: &Option>) -> Result> { if devices.is_none() { log::trace!("No ESP detected"); return Ok(None); @@ -317,7 +329,7 @@ impl Component for Efi { updatemeta: &ContentMetadata, with_static_config: bool, ) -> Result> { - let esp_devices = blockdev::find_colocated_esps(&rootcxt.devices)?; + let esp_devices = rootcxt.device.find_colocated_esps()?; let Some(meta) = self.query_adopt(&esp_devices)? else { return Ok(None); }; @@ -339,7 +351,8 @@ impl Component for Efi { let esp_devices = esp_devices.unwrap_or_default(); for esp in esp_devices { - let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp))?; + let destpath = + &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp.path()))?; let efidir = openat::Dir::open(&destpath.join("EFI")).context("opening EFI dir")?; validate_esp_fstype(&efidir)?; @@ -379,7 +392,7 @@ impl Component for Efi { &self, src_root: &str, dest_root: &str, - device: &str, + device: Option<&Device>, update_firmware: bool, ) -> Result { let src_dir = openat::Dir::open(src_root) @@ -389,19 +402,24 @@ impl Component for Efi { }; log::debug!("Found metadata {}", meta.version); - // Let's attempt to use an already mounted ESP at the target - // dest_root if one is already mounted there in a known ESP location. - let destpath = if let Some(destdir) = self.get_mounted_esp(Path::new(dest_root))? { + // Determine the destination path for the ESP. + // If a device is provided, find and mount its ESP partition (unmounting + // any previously mounted ESP first to target the correct device). + // If no device is provided, fall back to an already-mounted ESP. + let destpath = if let Some(dev) = device { + // Unmount any previously mounted ESP to ensure we install to the + // correct device. This is important for multi-device installs where + // each device has its own ESP. + self.unmount()?; + + let esp_device = dev + .find_partition_of_esp() + .with_context(|| format!("Failed to find ESP device on {}", dev.path()))?; + self.mount_esp_device(Path::new(dest_root), Path::new(&esp_device.path()))? + } else if let Some(destdir) = self.get_mounted_esp(Path::new(dest_root))? { destdir } else { - // Using `blockdev` to find the partition instead of partlabel because - // we know the target install toplevel device already. - if device.is_empty() { - anyhow::bail!("Device value not provided"); - } - let esp_device = blockdev::get_esp_partition(device)? - .ok_or_else(|| anyhow::anyhow!("Failed to find ESP device"))?; - self.mount_esp_device(Path::new(dest_root), Path::new(&esp_device))? + anyhow::bail!("No device specified and no mounted ESP found"); }; let destd = &openat::Dir::open(&destpath) @@ -438,8 +456,12 @@ impl Component for Efi { // Get filetree from efi path let ft = crate::filetree::FileTree::new_from_dir(&src_dir.sub_dir(efi_path)?)?; if update_firmware { - if let Some(vendordir) = self.get_efi_vendor(src_path.join(efi_path).as_std_path())? { - self.update_firmware(device, destd, &vendordir)? + if let Some(dev) = device { + if let Some(vendordir) = + self.get_efi_vendor(src_path.join(efi_path).as_std_path())? + { + self.update_firmware(dev, destd, &vendordir)? + } } } Ok(InstalledContent { @@ -477,12 +499,13 @@ impl Component for Efi { let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?; let diff = currentf.diff(&updatef)?; - let Some(esp_devices) = blockdev::find_colocated_esps(&rootcxt.devices)? else { + let Some(esp_devices) = rootcxt.device.find_colocated_esps()? else { anyhow::bail!("Failed to find all esp devices"); }; for esp in esp_devices { - let destpath = &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp))?; + let destpath = + &self.ensure_mounted_esp(rootcxt.path.as_ref(), Path::new(&esp.path()))?; let destdir = openat::Dir::open(&destpath.join("EFI")).context("opening EFI dir")?; validate_esp_fstype(&destdir)?; log::trace!("applying diff: {}", &diff); @@ -560,8 +583,8 @@ impl Component for Efi { } fn validate(&self, current: &InstalledContent) -> Result { - let devices = crate::blockdev::get_devices("/").context("get parent devices")?; - let esp_devices = blockdev::find_colocated_esps(&devices)?; + let device = bootc_internal_blockdev::list_dev(Utf8Path::new("/").into())?; + let esp_devices = device.find_colocated_esps()?; if !is_efi_booted()? && esp_devices.is_none() { return Ok(ValidationResult::Skip); } @@ -573,7 +596,7 @@ impl Component for Efi { let mut errs = Vec::new(); let esp_devices = esp_devices.unwrap_or_default(); for esp in esp_devices.iter() { - let destpath = &self.ensure_mounted_esp(Path::new("/"), Path::new(&esp))?; + let destpath = &self.ensure_mounted_esp(Path::new("/"), Path::new(&esp.path()))?; let efidir = openat::Dir::open(&destpath.join("EFI")) .with_context(|| format!("opening EFI dir {}", destpath.display()))?; From e61077b18e0b875753cf6510c259d9995734f237 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 4 Mar 2026 14:52:23 -0500 Subject: [PATCH 6/9] install: Enable installing to multiple devices or --filesystem This adds a new --filesystem flag that will use the blockdev crate to determine the parent devices of the root filesystem and install the bootloader to each device. The devices can also be explicitly specified via multiple --device flags. Signed-off-by: ckyrouac --- src/bios.rs | 21 ++++++---- src/bootupd.rs | 102 +++++++++++++++++++++++++++++++++++++++------ src/cli/bootupd.rs | 30 +++++++++++-- src/component.rs | 2 +- src/efi.rs | 15 ++++++- 5 files changed, 143 insertions(+), 27 deletions(-) diff --git a/src/bios.rs b/src/bios.rs index af4444d3..22fae3dc 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -122,7 +122,9 @@ impl Component for Bios { anyhow::bail!("No update metadata for component {} found", self.name()); }; - self.run_grub_install(dest_root, &device.path())?; + self.run_grub_install(dest_root, &device.path()) + .with_context(|| format!("installing GRUB on {}", device.path()))?; + Ok(InstalledContent { meta, filetree: None, @@ -222,9 +224,12 @@ impl Component for Bios { return Ok(None); }; - for parent in rootcxt.devices.iter() { - self.run_grub_install(rootcxt.path.as_str(), &parent)?; - log::debug!("Installed grub modules on {parent}"); + // Install grub onto each parent (whole-disk) device. For BIOS boot on + // multi-disk setups (e.g. RAID), grub must be written to every backing + // disk's MBR/BIOS-boot partition so the system can boot from any one. + for parent in rootcxt.device.find_all_roots()? { + self.run_grub_install(rootcxt.path.as_str(), &parent.path())?; + log::debug!("Installed grub modules on {}", parent.path()); } if with_static_config { @@ -259,9 +264,9 @@ impl Component for Bios { .query_update(&rootcxt.sysroot)? .expect("update available"); - for parent in rootcxt.devices.iter() { - self.run_grub_install(rootcxt.path.as_str(), &parent)?; - log::debug!("Installed grub modules on {parent}"); + for parent in rootcxt.device.find_all_roots()? { + self.run_grub_install(rootcxt.path.as_str(), &parent.path())?; + log::debug!("Installed grub modules on {}", parent.path()); } let adopted_from = None; @@ -272,7 +277,7 @@ impl Component for Bios { }) } - fn validate(&self, _: &InstalledContent) -> Result { + fn validate(&self, _: &InstalledContent, _device: &Device) -> Result { Ok(ValidationResult::Skip) } diff --git a/src/bootupd.rs b/src/bootupd.rs index 98100266..e01ce923 100644 --- a/src/bootupd.rs +++ b/src/bootupd.rs @@ -32,6 +32,8 @@ use std::io::{BufRead, BufReader, BufWriter, Write}; use std::path::{Path, PathBuf}; use bootc_internal_blockdev::Device; +use cap_std::fs::Dir; +use cap_std_ext::cap_std; pub(crate) enum ConfigMode { None, @@ -107,15 +109,70 @@ pub(crate) fn install( continue; } - let meta = component - .install(&source_root, dest_root, device, update_firmware) - .with_context(|| format!("installing component {}", component.name()))?; - log::info!("Installed {} {}", component.name(), meta.meta.version); - state.installed.insert(component.name().into(), meta); - // Yes this is a hack...the Component thing just turns out to be too generic. - if let Some(vendor) = component.get_efi_vendor(&Path::new(source_root))? { - assert!(installed_efi_vendor.is_none()); - installed_efi_vendor = Some(vendor); + // Determine which devices to install to. For EFI, filter to only + // devices that have an ESP partition. + let devices_to_install: Vec> = if devices.is_empty() { + // No devices specified: install once with auto-detection (None). + vec![None] + } else if component.name() == "EFI" { + // For EFI, only install to devices that have an ESP partition. + let esp_devices: Vec<&Device> = devices + .iter() + .filter(|dev| match dev.find_partition_of_esp() { + Ok(_) => true, + Err(e) => { + log::warn!("Skipping device {} for EFI: {:#}", dev.path(), e); + false + } + }) + .collect(); + if esp_devices.is_empty() { + // No devices had a detectable ESP partition. This can happen with + // loopback devices or other setups where partition scanning fails. + // Fall back to auto-detection — the EFI component will look for + // an already-mounted ESP at the destination. + log::info!( + "No ESP partitions detected on specified devices; \ + falling back to mounted ESP detection" + ); + vec![None] + } else { + esp_devices.into_iter().map(Some).collect() + } + } else { + devices.iter().map(|dev| Some(dev)).collect() + }; + + for device in &devices_to_install { + let device_desc = device.map_or("(auto)".to_string(), |d| d.path()); + let meta = component + .install(source_root, dest_root, *device, update_firmware) + .with_context(|| { + format!( + "installing component {} to device {}", + component.name(), + device_desc, + ) + })?; + log::info!( + "Installed {} {} to {}", + component.name(), + meta.meta.version, + device_desc, + ); + // State is tracked per-component, not per-device. The metadata + // (version, filetree, etc.) is identical across all devices, so we + // only need to record it once. Updates and validation discover all + // colocated devices at runtime (e.g. via find_colocated_esps()). + if !state.installed.contains_key(component.name()) { + state.installed.insert(component.name().into(), meta); + } + // Yes this is a hack...the Component thing just turns out to be too generic. + if installed_efi_vendor.is_none() { + if let Some(vendor) = component.get_efi_vendor(Path::new(source_root))? { + installed_efi_vendor = Some(vendor); + } + } } } let sysroot = &openat::Dir::open(dest_root)?; @@ -367,6 +424,22 @@ pub(crate) fn adopt_and_update( } } +/// Get the block device backing the current root by trying `/boot` first, +/// then falling back to `/sysroot`. This avoids issues with virtual +/// filesystems like composefs that are mounted on `/`. +#[context("Finding block device from boot or sysroot")] +fn list_dev_current_root() -> Result { + let auth = cap_std::ambient_authority(); + for path in ["/boot", "/sysroot"] { + if let Ok(dir) = Dir::open_ambient_dir(path, auth) { + if let Ok(dev) = bootc_internal_blockdev::list_dev_by_dir(&dir) { + return Ok(dev); + } + } + } + anyhow::bail!("Failed to find block device from /boot or /sysroot") +} + /// daemon implementation of component validate pub(crate) fn validate(name: &str) -> Result { let state = SavedState::load_from_disk("/")?.unwrap_or_default(); @@ -374,7 +447,8 @@ pub(crate) fn validate(name: &str) -> Result { let Some(inst) = state.installed.get(name) else { anyhow::bail!("Component {} is not installed", name); }; - component.validate(inst) + let device = list_dev_current_root()?; + component.validate(inst, &device) } pub(crate) fn status() -> Result { @@ -518,8 +592,10 @@ pub struct RootContext { pub sysroot: openat::Dir, pub path: Utf8PathBuf, - // The block device backing the root filesystem. - // This is used to determine the device to install to for components that need it, and also passed to component update/adoption logic which may need it for validation or other purposes. + /// The block device backing the root filesystem. + /// + /// Used to determine the device to install to for components that need + /// it, and passed to component update/adoption logic for validation. pub device: Device, } @@ -537,7 +613,7 @@ impl RootContext { fn prep_before_update() -> Result { let path = "/"; let sysroot = openat::Dir::open(path).context("Opening root dir")?; - let device = bootc_internal_blockdev::list_dev(Utf8Path::new(path).into())?; + let device = list_dev_current_root()?; Ok(RootContext::new(sysroot, path, device)) } diff --git a/src/cli/bootupd.rs b/src/cli/bootupd.rs index 4a6b8cf1..10e0f256 100644 --- a/src/cli/bootupd.rs +++ b/src/cli/bootupd.rs @@ -1,5 +1,8 @@ use crate::bootupd::{self, ConfigMode}; use anyhow::{Context, Result}; +use camino::Utf8Path; +use cap_std::fs::Dir; +use cap_std_ext::cap_std; use clap::Parser; use log::LevelFilter; @@ -46,9 +49,15 @@ pub struct InstallOpts { #[clap(value_parser)] dest_root: String, - /// Target device, used by bios bootloader installation + /// Target device(s) for bootloader installation. Can be specified multiple + /// times to install to multiple devices (e.g., for multi-disk RAID/LVM setups). + #[clap(long, action = clap::ArgAction::Append, conflicts_with = "filesystem")] + device: Vec, + + /// Filesystem path to inspect for backing devices. Bootupd will walk up the + /// device hierarchy to find physical disks and install to all ESPs found. #[clap(long)] - device: Option, + filesystem: Option, /// Enable installation of the built-in static config files #[clap(long)] @@ -110,10 +119,25 @@ impl DCommand { } else { ConfigMode::None }; + + // Resolve devices: either discover backing devices from a filesystem path, + // or convert explicitly specified device paths to Device objects. + let devices = if let Some(ref fs_path) = opts.filesystem { + let dir = Dir::open_ambient_dir(fs_path, cap_std::ambient_authority()) + .with_context(|| format!("Opening filesystem path {fs_path}"))?; + let device = bootc_internal_blockdev::list_dev_by_dir(&dir)?; + device.find_all_roots()? + } else { + opts.device + .iter() + .map(|d| bootc_internal_blockdev::list_dev(Utf8Path::new(d))) + .collect::>>()? + }; + bootupd::install( &opts.src_root, &opts.dest_root, - opts.device.as_deref(), + &devices, configmode, opts.update_firmware, opts.components.as_deref(), diff --git a/src/component.rs b/src/component.rs index edce556a..dabcea97 100644 --- a/src/component.rs +++ b/src/component.rs @@ -81,7 +81,7 @@ pub(crate) trait Component { ) -> Result; /// Used on the client to validate an installed version. - fn validate(&self, current: &InstalledContent) -> Result; + fn validate(&self, current: &InstalledContent, device: &Device) -> Result; /// Locating efi vendor dir fn get_efi_vendor(&self, sysroot: &Path) -> Result>; diff --git a/src/efi.rs b/src/efi.rs index 5786a4c6..e08b2f2b 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -86,6 +86,18 @@ impl Efi { let st = rustix::fs::statfs(&path)?; if st.f_type == libc::MSDOS_SUPER_MAGIC { + // Verify this is actually a mount point, not just a subdirectory + // on a vfat filesystem. Compare device IDs: a mount point has a + // different device than its parent. Without this check, a vfat + // subdirectory (e.g. /boot/efi on a vfat /boot) could be + // misidentified as a mounted ESP. + let path_dev = std::fs::metadata(&path)?.dev(); + let parent_dev = std::fs::metadata(path.parent().unwrap_or(&path))?.dev(); + if path_dev == parent_dev { + // Same device as parent - this is a subdirectory, not a mount point + log::debug!("Skipping {path:?}: vfat but not a mount point"); + continue; + } util::ensure_writable_mount(&path)?; found_mount = Some(path); break; @@ -582,8 +594,7 @@ impl Component for Efi { Ok(content_metadata) } - fn validate(&self, current: &InstalledContent) -> Result { - let device = bootc_internal_blockdev::list_dev(Utf8Path::new("/").into())?; + fn validate(&self, current: &InstalledContent, device: &Device) -> Result { let esp_devices = device.find_colocated_esps()?; if !is_efi_booted()? && esp_devices.is_none() { return Ok(ValidationResult::Skip); From 2bf2dfbf83fe6cd6c9ec0751b9434a9692f7a998 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Thu, 5 Mar 2026 11:39:56 -0500 Subject: [PATCH 7/9] efi: Handle already-mounted ESP in mount_esp_device When running install-to-filesystem, the host may already have the ESP mounted (e.g. /dev/sda15 at /boot/efi). Previously mount_esp_device would unconditionally call mount, which fails with "already mounted". Check if the mount point already contains a vfat filesystem on a different device than its parent (i.e. is a real mount point) before attempting to mount, and reuse the existing mount if so. Assisted-by: Claude Code (Opus 4) Signed-off-by: ckyrouac --- src/efi.rs | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/efi.rs b/src/efi.rs index e08b2f2b..1022f4af 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -5,7 +5,6 @@ */ use std::cell::RefCell; -use std::os::unix::fs::MetadataExt; use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; use std::process::Command; @@ -61,6 +60,26 @@ const STUB_INFO_VAR_STR: &str = "StubInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"; /// The options of cp command for installation const OPTIONS: &[&str] = &["-rp", "--reflink=auto"]; +/// Check if the given path is a mount point via statx(MOUNT_ROOT). +fn is_mount_point(path: &Path) -> Result { + use rustix::fs::{AtFlags, StatxAttributes, StatxFlags}; + // See https://github.com/coreos/cap-std-ext/blob/5493d689/src/dirext.rs#L514 + // CWD is unused here because callers always pass absolute paths. + let r = rustix::fs::statx( + rustix::fs::CWD, + path, + AtFlags::NO_AUTOMOUNT | AtFlags::SYMLINK_NOFOLLOW, + StatxFlags::empty(), + )?; + if r.stx_attributes_mask.contains(StatxAttributes::MOUNT_ROOT) { + Ok(r.stx_attributes.contains(StatxAttributes::MOUNT_ROOT)) + } else { + anyhow::bail!( + "could not determine if {path:?} is a mount point (kernel too old for MOUNT_ROOT)" + ) + } +} + /// Return `true` if the system is booted via EFI pub(crate) fn is_efi_booted() -> Result { Path::new("/sys/firmware/efi") @@ -91,9 +110,7 @@ impl Efi { // different device than its parent. Without this check, a vfat // subdirectory (e.g. /boot/efi on a vfat /boot) could be // misidentified as a mounted ESP. - let path_dev = std::fs::metadata(&path)?.dev(); - let parent_dev = std::fs::metadata(path.parent().unwrap_or(&path))?.dev(); - if path_dev == parent_dev { + if !is_mount_point(&path)? { // Same device as parent - this is a subdirectory, not a mount point log::debug!("Skipping {path:?}: vfat but not a mount point"); continue; @@ -123,6 +140,18 @@ impl Efi { if !mnt.exists() { continue; } + + // Check if the target is already a mounted ESP (e.g. the host + // already has the ESP mounted when running install-to-filesystem). + let st = rustix::fs::statfs(&mnt)?; + if st.f_type == libc::MSDOS_SUPER_MAGIC { + if is_mount_point(&mnt)? { + log::debug!("ESP already mounted at {mnt:?}, reusing"); + mountpoint = Some(mnt); + break; + } + } + std::process::Command::new("mount") .arg(&esp_device) .arg(&mnt) From e13e60cb8b15cd227312024333b646bb00cd383e Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Wed, 11 Mar 2026 08:57:01 -0400 Subject: [PATCH 8/9] spec: Add conflict with bootc < 1.14.0 Signed-off-by: ckyrouac --- contrib/packaging/bootupd.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/packaging/bootupd.spec b/contrib/packaging/bootupd.spec index f7c4e541..a5b5f65d 100644 --- a/contrib/packaging/bootupd.spec +++ b/contrib/packaging/bootupd.spec @@ -42,6 +42,7 @@ Summary: %{summary} # Unlicense OR MIT License: Apache-2.0 AND (Apache-2.0 WITH LLVM-exception) AND BSD-3-Clause AND MIT AND (Apache-2.0 OR BSL-1.0) AND (Apache-2.0 OR MIT) AND (Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT) AND (Unlicense OR MIT) %{?systemd_requires} +Conflicts: bootc < 1.14.1 %description -n %{crate} %{_description} From 7d0b7354dea25a64fb5d1e07fdb926bf5fa7e708 Mon Sep 17 00:00:00 2001 From: ckyrouac Date: Mon, 16 Mar 2026 15:38:38 -0400 Subject: [PATCH 9/9] ci: Install bootc from rhcontainerbot/bootc copr repo This uses the latest bootc RPM built from main in the CI tests. Assisted-by: Claude Code (Opus 4) Signed-off-by: ckyrouac --- Dockerfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Dockerfile b/Dockerfile index 928b0acf..a0a75e4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,18 @@ FROM $base # Clean out the default to ensure we're using our updated content RUN rpm -e bootupd COPY --from=build /out/ / +# Install bootc from copr +RUN <