Skip to content

Commit 21447f2

Browse files
authored
Merge pull request #688 from cgwalters/blockdev-sfdisk
install: Use sfdisk, not lsblk
2 parents 89635a8 + 8e7f6e0 commit 21447f2

File tree

4 files changed

+102
-5
lines changed

4 files changed

+102
-5
lines changed

lib/src/blockdev.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,58 @@ pub(crate) fn list() -> Result<Vec<Device>> {
124124
list_impl(None)
125125
}
126126

127+
#[derive(Debug, Deserialize)]
128+
struct SfDiskOutput {
129+
partitiontable: PartitionTable,
130+
}
131+
132+
#[derive(Debug, Deserialize)]
133+
#[allow(dead_code)]
134+
pub(crate) struct Partition {
135+
pub(crate) node: String,
136+
pub(crate) start: u64,
137+
pub(crate) size: u64,
138+
#[serde(rename = "type")]
139+
pub(crate) parttype: String,
140+
pub(crate) uuid: Option<String>,
141+
pub(crate) name: Option<String>,
142+
}
143+
144+
#[derive(Debug, Deserialize)]
145+
#[allow(dead_code)]
146+
pub(crate) struct PartitionTable {
147+
pub(crate) label: String,
148+
pub(crate) id: String,
149+
pub(crate) device: String,
150+
// We're not using these fields
151+
// pub(crate) unit: String,
152+
// pub(crate) firstlba: u64,
153+
// pub(crate) lastlba: u64,
154+
// pub(crate) sectorsize: u64,
155+
pub(crate) partitions: Vec<Partition>,
156+
}
157+
158+
impl PartitionTable {
159+
/// Find the partition with the given device name
160+
#[allow(dead_code)]
161+
pub(crate) fn find<'a>(&'a self, devname: &str) -> Option<&'a Partition> {
162+
self.partitions.iter().find(|p| p.node.as_str() == devname)
163+
}
164+
165+
pub(crate) fn path(&self) -> &Utf8Path {
166+
self.device.as_str().into()
167+
}
168+
}
169+
170+
#[context("Listing partitions of {dev}")]
171+
pub(crate) fn partitions_of(dev: &Utf8Path) -> Result<PartitionTable> {
172+
let o = Task::new_quiet("sfdisk")
173+
.args(["-J", dev.as_str()])
174+
.read()?;
175+
let o: SfDiskOutput = serde_json::from_str(&o).context("Parsing sfdisk output")?;
176+
Ok(o.partitiontable)
177+
}
178+
127179
pub(crate) struct LoopbackDevice {
128180
pub(crate) dev: Option<Utf8PathBuf>,
129181
}
@@ -324,3 +376,48 @@ fn test_parse_size_mib() {
324376
assert_eq!(parse_size_mib(&s).unwrap(), v as u64, "Parsing {s}");
325377
}
326378
}
379+
380+
#[cfg(test)]
381+
mod test {
382+
use super::*;
383+
384+
#[test]
385+
fn test_parse_sfdisk() -> Result<()> {
386+
let fixture = indoc::indoc! { r#"
387+
{
388+
"partitiontable": {
389+
"label": "gpt",
390+
"id": "A67AA901-2C72-4818-B098-7F1CAC127279",
391+
"device": "/dev/loop0",
392+
"unit": "sectors",
393+
"firstlba": 34,
394+
"lastlba": 20971486,
395+
"sectorsize": 512,
396+
"partitions": [
397+
{
398+
"node": "/dev/loop0p1",
399+
"start": 2048,
400+
"size": 8192,
401+
"type": "9E1A2D38-C612-4316-AA26-8B49521E5A8B",
402+
"uuid": "58A4C5F0-BD12-424C-B563-195AC65A25DD",
403+
"name": "PowerPC-PReP-boot"
404+
},{
405+
"node": "/dev/loop0p2",
406+
"start": 10240,
407+
"size": 20961247,
408+
"type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
409+
"uuid": "F51ABB0D-DA16-4A21-83CB-37F4C805AAA0",
410+
"name": "root"
411+
}
412+
]
413+
}
414+
}
415+
"# };
416+
let table: SfDiskOutput = serde_json::from_str(&fixture).unwrap();
417+
assert_eq!(
418+
table.partitiontable.find("/dev/loop0p2").unwrap().size,
419+
20961247
420+
);
421+
Ok(())
422+
}
423+
}

lib/src/bootloader.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use anyhow::Result;
22
use camino::Utf8Path;
33
use fn_error_context::context;
44

5-
use crate::blockdev::Device;
5+
use crate::blockdev::PartitionTable;
66
use crate::task::Task;
77

88
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
99
pub(crate) const EFI_DIR: &str = "efi";
1010

1111
#[context("Installing bootloader")]
1212
pub(crate) fn install_via_bootupd(
13-
device: &Device,
13+
device: &PartitionTable,
1414
rootfs: &Utf8Path,
1515
configopts: &crate::install::InstallConfigOpts,
1616
) -> Result<()> {

lib/src/install.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ fn require_skopeo_with_containers_storage() -> Result<()> {
823823

824824
pub(crate) struct RootSetup {
825825
luks_device: Option<String>,
826-
device_info: crate::blockdev::Device,
826+
device_info: crate::blockdev::PartitionTable,
827827
rootfs: Utf8PathBuf,
828828
rootfs_fd: Dir,
829829
rootfs_uuid: Option<String>,
@@ -1598,7 +1598,7 @@ pub(crate) async fn install_to_filesystem(
15981598
dev
15991599
};
16001600
tracing::debug!("Backing device: {backing_device}");
1601-
let device_info = crate::blockdev::list_dev(Utf8Path::new(&backing_device))?;
1601+
let device_info = crate::blockdev::partitions_of(Utf8Path::new(&backing_device))?;
16021602

16031603
let rootarg = format!("root={}", root_info.mount_spec);
16041604
let mut boot = if let Some(spec) = fsopts.boot_mount_spec {

lib/src/install/baseline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ pub(crate) fn install_create_rootfs(
439439
BlockSetup::Direct => None,
440440
BlockSetup::Tpm2Luks => Some(luks_name.to_string()),
441441
};
442-
let device_info = crate::blockdev::list_dev(&devpath)?;
442+
let device_info = crate::blockdev::partitions_of(&devpath)?;
443443
Ok(RootSetup {
444444
luks_device,
445445
device_info,

0 commit comments

Comments
 (0)