max / alloy
- Co-Authored-By
- Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 file changed,
+28 insertions,
-1 deletion
| @@ -886,7 +886,13 @@ | |||
| 886 | 886 | Ok(parsed | |
| 887 | 887 | .blockdevices | |
| 888 | 888 | .into_iter() | |
| 889 | - | .filter(|device| device.kind == "disk" && !is_virtual(&device.name)) | |
| 889 | + | // A zero-byte disk is a slot, not a disk: an unconnected nbd node, or a | |
| 890 | + | // card reader with no card in it. lsblk types both as `disk` and both | |
| 891 | + | // would otherwise render as a pickable row, so the user can confirm a | |
| 892 | + | // wipe and only find out it was nothing partway through the install. | |
| 893 | + | // Filtered on size rather than by name because the name varies with | |
| 894 | + | // whatever presents the empty slot, and no real target reports zero. | |
| 895 | + | .filter(|device| device.kind == "disk" && !is_virtual(&device.name) && device.size > 0) | |
| 890 | 896 | .map(|device| { | |
| 891 | 897 | let mut mountpoints = Vec::new(); | |
| 892 | 898 | mountpoints_of(&device, &mut mountpoints); | |
| @@ -1562,6 +1568,27 @@ | |||
| 1562 | 1568 | ); | |
| 1563 | 1569 | } | |
| 1564 | 1570 | ||
| 1571 | + | // An empty slot reports `type: "disk"` at zero bytes: an unconnected nbd | |
| 1572 | + | // node, or a card reader with nothing in it. Found on fw13, where loading | |
| 1573 | + | // the nbd module put fifteen of them in the picker. Offering one means the | |
| 1574 | + | // user confirms a wipe and the install fails partway through against | |
| 1575 | + | // nothing. | |
| 1576 | + | #[test] | |
| 1577 | + | fn an_empty_slot_is_not_offered_as_a_target() { | |
| 1578 | + | let raw = r#"{"blockdevices":[ | |
| 1579 | + | {"name": "nbd0", "path": "/dev/nbd0", "size": 0, "type": "disk", | |
| 1580 | + | "rm": false, "ro": false, "mountpoints": [null]}, | |
| 1581 | + | {"name": "sdb", "path": "/dev/sdb", "size": 61530439680, "type": "disk", | |
| 1582 | + | "rm": true, "ro": false, "mountpoints": [null]} | |
| 1583 | + | ]}"#; | |
| 1584 | + | let names: Vec<String> = parse_disks(raw) | |
| 1585 | + | .unwrap() | |
| 1586 | + | .into_iter() | |
| 1587 | + | .map(|disk| disk.name) | |
| 1588 | + | .collect(); | |
| 1589 | + | assert_eq!(names, ["sdb"], "a zero-byte slot was offered as a target"); | |
| 1590 | + | } | |
| 1591 | + | ||
| 1565 | 1592 | #[test] | |
| 1566 | 1593 | fn real_disks_survive_with_their_identifying_details() { | |
| 1567 | 1594 | let disks = disks(); |