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