Adding ability to handle non bcachefs as root filesystem

This commit is contained in:
2026-09-22 17:25:02 +02:00
parent 63cb87888b
commit f388a879ea
4 changed files with 80 additions and 39 deletions
Generated
+1 -1
View File
@@ -284,7 +284,7 @@ checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
[[package]]
name = "nyanit"
version = "0.2.2"
version = "0.2.3"
dependencies = [
"nix",
"ratatui",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nyanit"
version = "0.2.2"
version = "0.2.3"
edition = "2024"
[dependencies]
+38 -25
View File
@@ -106,6 +106,9 @@ enum NyanitState {
HandOff,
}
///
/// Generates confirm dialog paragraph
///
fn gen_conf_par<'a>(snap_dt: String) -> Paragraph<'a> {
let first_line = Line::from(vec![Span::raw(CONFIRM_TEXT1), Span::raw(snap_dt).bold()]);
let confirm_line = Line::from(vec![
@@ -132,7 +135,7 @@ fn gen_conf_par<'a>(snap_dt: String) -> Paragraph<'a> {
struct NyanitTUI<'a> {
exit: bool,
state: NyanitState,
bee_root_dev: String,
bee_root_dev: nyan_system::BlkIdRes,
list_state: ListState,
/// time counter manly for F2 waiting in mills
time_counter: u64,
@@ -148,7 +151,10 @@ impl NyanitTUI<'_> {
Ok(Self {
exit: false,
state: NyanitState::Init,
bee_root_dev: String::new(),
bee_root_dev: nyan_system::BlkIdRes {
fs_type: String::new(),
dev_node: String::new(),
},
list_state: ListState::default().with_selected(Some(0)),
time_counter: 0,
time_counter_sec: 0,
@@ -166,24 +172,28 @@ impl NyanitTUI<'_> {
// let root_list = nyan_system::list_dir(TMP_ROOT)?;
// return Err(ExecCommandError::Other(root_list));
// list snaps if any
self.snaps_list = nyan_system::list_bzzpss_snaps(TMP_ROOT_SNAPS)?;
if self.bee_root_dev.is_bcachefs() {
// list snaps if any
self.snaps_list = nyan_system::list_bzzpss_snaps(TMP_ROOT_SNAPS)?;
// if any snaps detected check hive DB update_status
if self.snaps_list.len() > 0 {
// if pac_lock accessible and exist - rolling back
if let Ok(Some(snap_date_time)) = nyan_system::check_pac_lock()
&& self.snaps_list.contains(&snap_date_time)
{
Ok(NyanitState::ConfirmRollback(snap_date_time))
// if any snaps detected check hive DB update_status
if self.snaps_list.len() > 0 {
// if pac_lock accessible and exist - rolling back
if let Ok(Some(snap_date_time)) = nyan_system::check_pac_lock()
&& self.snaps_list.contains(&snap_date_time)
{
Ok(NyanitState::ConfirmRollback(snap_date_time))
}
// else user choose what to do
else {
Ok(NyanitState::WaitForF2)
}
}
// else user choose what to do
// else tell to finish boot
else {
Ok(NyanitState::WaitForF2)
Ok(NyanitState::HandOff)
}
}
// else tell to finish boot
else {
} else {
Ok(NyanitState::HandOff)
}
}
@@ -194,17 +204,17 @@ impl NyanitTUI<'_> {
// get bee-root device name aka /dev/sda1
// trying for max 3 sec
self.bee_root_dev = nyan_system::try_find_partlabel(ROOT_PARTLABEL, 3)
.ok_or_else(|| "Timed out trying to find dev by partlabel.".to_string())?;
// works until this point!!!!
// check if device is encrypted
if nyan_system::bzzpss_dev_encrypted(&self.bee_root_dev)
.map_err(|ex| format!("Error checking if device is encrypted: {}", ex))?
{
// if encrypted return EnterPassword so user get promted for pass
return Ok(NyanitState::EnterPassword);
if self.bee_root_dev.is_bcachefs() {
// check if device is encrypted
if nyan_system::bzzpss_dev_encrypted(&self.bee_root_dev.dev_node)
.map_err(|ex| format!("Error checking if device is encrypted: {}", ex))?
{
// if encrypted return EnterPassword so user get promted for pass
return Ok(NyanitState::EnterPassword);
}
}
// if unencrypted
@@ -453,7 +463,10 @@ impl NyanitTUI<'_> {
// try to unlock if enter pressed
Key::Char('\n') => {
let password = self.textarea.as_ref().unwrap().lines()[0].clone();
match nyan_system::bcachefs_unlock(password, &self.bee_root_dev) {
match nyan_system::bcachefs_unlock(
password,
&self.bee_root_dev.dev_node,
) {
Ok(unlocked) => {
if unlocked {
// need to check for subvolumes and stuff
+40 -12
View File
@@ -21,6 +21,7 @@
use nix;
use std::fs;
use std::process::Command;
use regex_lite::Regex;
/// timeout for block deices population
@@ -137,7 +138,28 @@ pub fn exec_command(cmd: &str, args: &Vec<&str>) -> Result<(), ExecCommandError>
}
}
pub fn try_find_partlabel(partlabel: &str, timeout_secs: u64) -> Option<String> {
#[derive(PartialEq)]
pub struct BlkIdRes {
pub fs_type: String,
pub dev_node: String,
}
impl BlkIdRes {
pub fn is_bcachefs(&self) -> bool {
if self.fs_type == "bcachefs" {
true
}
else {
false
}
}
}
///
/// Will block up to timeout_secs
///
pub fn try_find_partlabel(partlabel: &str, timeout_secs: u64) -> Option<BlkIdRes> {
use std::{thread, time::Duration};
let start = std::time::Instant::now();
@@ -152,9 +174,11 @@ pub fn try_find_partlabel(partlabel: &str, timeout_secs: u64) -> Option<String>
/// Gets device node aka /dev/sda1 from gpr partition label
/// blkid -s PARTLABEL --match-token PARTLABEL="bzz-primary"
pub fn find_partlabel(partlabel: &str) -> Result<Option<String>, ExecCommandError> {
pub fn find_partlabel(partlabel: &str) -> Result<Option<BlkIdRes>, ExecCommandError> {
let out = Command::new("/usr/bin/blkid")
.args([
"-s",
"TYPE",
"-s",
"PARTLABEL",
"-t",
@@ -162,13 +186,18 @@ pub fn find_partlabel(partlabel: &str) -> Result<Option<String>, ExecCommandErro
])
.output()?;
if out.status.success() {
let re = Regex::new(r#"^(/dev/[a-z0-9-]+): TYPE="([a-z]+)" PARTLABEL="[a-z]+"$"#)
.unwrap();
let out_text = String::from_utf8(out.stdout)?;
let split_res = out_text.split_once(':').ok_or_else(|| {
ExecCommandError::Other(format!("Unexpected blkid output format: \"{}\"", out_text))
})?;
Ok(Some(split_res.0.to_string()))
if let Some(captured) = re.captures(&out_text) {
// let part_no = captured[1];
// let parent_dev = captured[2];
let res = BlkIdRes{ fs_type: captured[2].to_string(), dev_node: captured[1].to_string()};
Ok(Some(res))
} else {
Err(ExecCommandError::Other(format!("Unexpected blkid output format: \"{}\"", out_text)))
}
} else {
if let Some(code) = out.status.code()
&& code == 2
@@ -272,7 +301,6 @@ pub fn bzzpss_dev_encrypted(dev_name: &str) -> Result<bool, ExecCommandError> {
/// And return list of date-time part of filename if both snapshots exists
///
pub fn list_bzzpss_snaps(snaps_dir: &str) -> Result<Vec<String>, ExecCommandError> {
use regex_lite::Regex;
use std::path::Path;
// usr or var snapshoot in a form of bzz-usr|var-yyyy-mm-ddTHH-MM-SS
@@ -741,22 +769,22 @@ pub fn prepare_env() -> Result<(), ExecCommandError> {
// }
// # Mount the real root filesystem
pub fn mount_bee_root(dev_name: &str, mount_point: &str) -> Result<(), ExecCommandError> {
pub fn mount_bee_root(device: &BlkIdRes, mount_point: &str) -> Result<(), ExecCommandError> {
use nix::mount::{MsFlags, mount};
use std::path::Path;
let root_mount_flags = MsFlags::MS_RDONLY | MsFlags::MS_RELATIME;
mount(
Some(dev_name),
Some(device.dev_node.as_str()),
Path::new(mount_point),
Some("bcachefs"),
Some(device.fs_type.as_str()),
root_mount_flags,
None::<&str>,
)
.map_err(|ex| {
format!(
"Error mounting root {} to {} :\n{}",
dev_name,
&device.dev_node,
mount_point,
ex.to_string()
)