1
0
forked from brl/citadel-tools

Clippy fixes

This commit is contained in:
Bruce Leidl 2019-04-03 16:05:09 -04:00
parent fab4106302
commit 7d89c47eb2
54 changed files with 360 additions and 368 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
**/target **/target
**/*.rs.bk **/*.rs.bk
**/*.iml

View File

@ -140,8 +140,8 @@ impl Backend {
} }
fn apply_colors(&self, colors: theme::ColorPair) { fn apply_colors(&self, colors: theme::ColorPair) {
with_color(&colors.front, |c| self.write(tcolor::Fg(c))); with_color(colors.front, |c| self.write(tcolor::Fg(c)));
with_color(&colors.back, |c| self.write(tcolor::Bg(c))); with_color(colors.back, |c| self.write(tcolor::Bg(c)));
} }
fn map_key(&mut self, event: TEvent) -> Event { fn map_key(&mut self, event: TEvent) -> Event {
@ -257,7 +257,7 @@ impl backend::Backend for Backend {
self.current_style.set(color); self.current_style.set(color);
} }
return current_style; current_style
} }
fn set_effect(&self, effect: theme::Effect) { fn set_effect(&self, effect: theme::Effect) {
@ -326,11 +326,11 @@ impl backend::Backend for Backend {
} }
} }
fn with_color<F, R>(clr: &theme::Color, f: F) -> R fn with_color<F, R>(clr: theme::Color, f: F) -> R
where where
F: FnOnce(&dyn tcolor::Color) -> R, F: FnOnce(&dyn tcolor::Color) -> R,
{ {
match *clr { match clr {
theme::Color::TerminalDefault => f(&tcolor::Reset), theme::Color::TerminalDefault => f(&tcolor::Reset),
theme::Color::Dark(theme::BaseColor::Black) => f(&tcolor::Black), theme::Color::Dark(theme::BaseColor::Black) => f(&tcolor::Black),
theme::Color::Dark(theme::BaseColor::Red) => f(&tcolor::Red), theme::Color::Dark(theme::BaseColor::Red) => f(&tcolor::Red),
@ -374,10 +374,8 @@ pub fn start_resize_thread(
// We know it will only contain SIGWINCH signals, so no need to check. // We know it will only contain SIGWINCH signals, so no need to check.
if signals.wait().count() > 0 { if signals.wait().count() > 0 {
// XXX fixed to avoid panic // XXX fixed to avoid panic
if resize_running.load(Ordering::Relaxed) { if resize_running.load(Ordering::Relaxed) && resize_sender.send(()).is_err() {
if let Err(_) = resize_sender.send(()) { return;
return;
}
} }
} }
} }

View File

@ -232,7 +232,7 @@ impl FieldLayout {
}; };
let labels = labels let labels = labels
.into_iter() .iter()
.map(pad_label) .map(pad_label)
.collect(); .collect();
@ -308,7 +308,7 @@ pub trait DialogButtonAdapter: Finder+ViewWrapper {
{ {
let id = self.inner_id(); let id = self.inner_id();
self.call_on_id(id, cb) self.call_on_id(id, cb)
.expect(format!("failed call_on_id({})", id).as_str()) .unwrap_or_else(|| panic!("failed call_on_id({})", id))
} }
fn button_enabled(&mut self, button: usize) -> bool { fn button_enabled(&mut self, button: usize) -> bool {
@ -322,9 +322,9 @@ pub trait DialogButtonAdapter: Finder+ViewWrapper {
fn set_button_enabled(&mut self, button: usize, enabled: bool) { fn set_button_enabled(&mut self, button: usize, enabled: bool) {
self.call_on_dialog(|d| { self.call_on_dialog(|d| {
d.buttons_mut() if let Some(b) = d.buttons_mut().nth(button) {
.nth(button) b.set_enabled(enabled);
.map(|b| b.set_enabled(enabled)); }
}) })
} }
@ -416,8 +416,7 @@ impl ValidatorResult {
fn process(self, siv: &mut Cursive) { fn process(self, siv: &mut Cursive) {
match self { match self {
ValidatorResult::Allow(cb) => (cb)(siv), ValidatorResult::Allow(cb) | ValidatorResult::Deny(cb) => (cb)(siv),
ValidatorResult::Deny(cb) => (cb)(siv),
} }
} }
@ -470,7 +469,7 @@ impl TextValidator {
where F: FnOnce(&mut EditView) -> R { where F: FnOnce(&mut EditView) -> R {
siv.call_on_id(&self.id, f) siv.call_on_id(&self.id, f)
.expect(&format!("call_on_id({})", self.id)) .unwrap_or_else(|| panic!("call_on_id({})", self.id))
} }
} }

View File

@ -134,8 +134,7 @@ impl <T: Clone + 'static> ItemList<T> {
where F: FnOnce(&mut ItemList<T>) -> R where F: FnOnce(&mut ItemList<T>) -> R
{ {
s.call_on_id(id, |v: &mut ItemList<T>| f(v)) s.call_on_id(id, |v: &mut ItemList<T>| f(v))
.expect(&format!("ItemList::call_on_id({})", id)) .unwrap_or_else(|| panic!("ItemList::call_on_id({})", id))
} }
pub fn create<C>(id: &'static str, title: &str, content: C) -> impl View pub fn create<C>(id: &'static str, title: &str, content: C) -> impl View
@ -294,7 +293,7 @@ impl Inner {
} }
fn pop_style(&mut self) -> Style { fn pop_style(&mut self) -> Style {
self.styles.pop().unwrap_or(Style::none()) self.styles.pop().unwrap_or_default()
} }
fn append(&mut self, s: StyledString) { fn append(&mut self, s: StyledString) {

View File

@ -79,10 +79,8 @@ impl RealmAction {
let msg = "Open terminal in realm '$REALM'?"; let msg = "Open terminal in realm '$REALM'?";
Self::confirm_action(title, msg, |r| { Self::confirm_action(title, msg, |r| {
let manager = r.manager(); let manager = r.manager();
if !r.is_active() { if !r.is_active() && !Self::log_fail("starting realm", || manager.start_realm(r)) {
if !Self::log_fail("starting realm", || manager.start_realm(r)) { return;
return;
}
} }
Self::log_fail("starting terminal", || manager.launch_terminal(r)); Self::log_fail("starting terminal", || manager.launch_terminal(r));
}) })
@ -146,7 +144,7 @@ impl RealmAction {
EventResult::with_cb(|s| { EventResult::with_cb(|s| {
let realm = RealmAction::current_realm(s); let realm = RealmAction::current_realm(s);
let desc = format!("realm-{}", realm.name()); let desc = format!("realm-{}", realm.name());
let notes = realm.notes().unwrap_or(String::new()); let notes = realm.notes().unwrap_or_default();
NotesDialog::open(s, &desc, notes, move |s, notes| { NotesDialog::open(s, &desc, notes, move |s, notes| {
if let Err(e) = realm.save_notes(notes) { if let Err(e) = realm.save_notes(notes) {
warn!("error saving notes file for realm-{}: {}", realm.name(), e); warn!("error saving notes file for realm-{}: {}", realm.name(), e);

View File

@ -153,7 +153,7 @@ impl ConfigDialog {
fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R
{ {
self.call_on_id(id, callback) self.call_on_id(id, callback)
.expect(format!("failed call_on_id({})", id).as_str()) .unwrap_or_else(|| panic!("failed call_on_id({})", id))
} }
pub fn reset_changes(&mut self) { pub fn reset_changes(&mut self) {
@ -372,15 +372,13 @@ impl OptionEntry {
fn load(&mut self, config: &mut RealmConfig) { fn load(&mut self, config: &mut RealmConfig) {
let var = (self.accessor)(config); let var = (self.accessor)(config);
self.value = var.clone(); self.value = *var;
self.original = var.clone(); self.original = *var;
self.default = self.resolve_default(config); self.default = self.resolve_default(config);
} }
fn set(&mut self, v: bool) { fn set(&mut self, v: bool) {
if v != self.default { if v != self.default || self.original == Some(v) {
self.value = Some(v);
} else if Some(v) == self.original {
self.value = Some(v); self.value = Some(v);
} else { } else {
self.value = None; self.value = None;

View File

@ -156,9 +156,9 @@ impl <'a> RealmInfoRender <'a> {
if self.realm.is_active() { if self.realm.is_active() {
self.print(" Running"); self.print(" Running");
self.realm.leader_pid().map(|pid| { if let Some(pid) = self.realm.leader_pid() {
self.print(format!(" (Leader pid: {})", pid)); self.print(format!(" (Leader pid: {})", pid));
}); }
} }
self.newlines(2); self.newlines(2);
} }

View File

@ -205,7 +205,7 @@ impl NewRealmDialog {
fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R
{ {
self.call_on_id(id, callback) self.call_on_id(id, callback)
.expect(format!("failed call_on_id({})", id).as_str()) .unwrap_or_else(|| panic!("failed call_on_id({})", id))
} }
} }
@ -320,7 +320,7 @@ impl NewRealmFSDialog {
fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R
{ {
self.call_on_id(id, callback) self.call_on_id(id, callback)
.expect(format!("failed call_on_id({})", id).as_str()) .unwrap_or_else(|| panic!("failed call_on_id({})", id))
} }
fn set_ok_button_enabled(&mut self, enabled: bool) { fn set_ok_button_enabled(&mut self, enabled: bool) {

View File

@ -169,7 +169,7 @@ impl RealmFSAction {
EventResult::with_cb(|s| { EventResult::with_cb(|s| {
let realmfs = Self::current_realmfs(s); let realmfs = Self::current_realmfs(s);
let desc = format!("{}-realmfs.img", realmfs.name()); let desc = format!("{}-realmfs.img", realmfs.name());
let notes = realmfs.notes().unwrap_or(String::new()); let notes = realmfs.notes().unwrap_or_default();
NotesDialog::open(s, &desc, notes, move |s, notes| { NotesDialog::open(s, &desc, notes, move |s, notes| {
if let Err(e) = realmfs.save_notes(notes) { if let Err(e) = realmfs.save_notes(notes) {
warn!("error saving notes file for {}-realmfs.img: {}", realmfs.name(), e); warn!("error saving notes file for {}-realmfs.img: {}", realmfs.name(), e);

View File

@ -113,7 +113,7 @@ impl ForkDialog {
fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R fn call_id<V: View, F: FnOnce(&mut V) -> R, R>(&mut self, id: &str, callback: F) -> R
{ {
self.call_on_id(id, callback) self.call_on_id(id, callback)
.expect(format!("failed call_on_id({})", id).as_str()) .unwrap_or_else(|| panic!("failed call_on_id({})", id))
} }
} }

View File

@ -227,7 +227,7 @@ impl <'a> RealmFSInfoRender <'a> {
self.print(" Device : ") self.print(" Device : ")
.dim_style() .dim_style()
.println(format!("{}", activation.device())) .println(activation.device())
.pop(); .pop();
let mount = if activation.mountpoint_rw().is_some() { "Mounts" } else { "Mount "}; let mount = if activation.mountpoint_rw().is_some() { "Mounts" } else { "Mount "};

View File

@ -46,7 +46,7 @@ impl ThemeHandler {
(0x3, "highlight_inactive"), (0x3, "highlight_inactive"),
]; ];
for pair in &mapping { for pair in &mapping {
ThemeHandler::set_palette_color(&mut theme, pair.1, base16.color(pair.0).rgb()); Self::set_palette_color(&mut theme, pair.1, base16.color(pair.0).rgb());
} }
theme theme
} }
@ -55,13 +55,13 @@ impl ThemeHandler {
const DEFAULT_SCHEME: &'static str = "default-dark"; const DEFAULT_SCHEME: &'static str = "default-dark";
pub fn save_base16_theme(base16: &Base16Scheme) { pub fn save_base16_theme(base16: &Base16Scheme) {
if let Err(e) = fs::write(ThemeHandler::SCHEME_CONF_PATH, base16.slug()) { if let Err(e) = fs::write(Self::SCHEME_CONF_PATH, base16.slug()) {
warn!("Error writing color scheme file ({}): {}", ThemeHandler::SCHEME_CONF_PATH, e); warn!("Error writing color scheme file ({}): {}", Self::SCHEME_CONF_PATH, e);
} }
} }
pub fn load_base16_scheme() -> Option<Base16Scheme> { pub fn load_base16_scheme() -> Option<Base16Scheme> {
let path = Path::new(ThemeHandler::SCHEME_CONF_PATH); let path = Path::new(Self::SCHEME_CONF_PATH);
if path.exists() { if path.exists() {
fs::read_to_string(path).ok().and_then(|ref s| Base16Scheme::by_name(s).cloned()) fs::read_to_string(path).ok().and_then(|ref s| Base16Scheme::by_name(s).cloned())
} else { } else {
@ -70,8 +70,8 @@ impl ThemeHandler {
} }
pub fn load_base16_theme() -> Theme { pub fn load_base16_theme() -> Theme {
let path = Path::new(ThemeHandler::SCHEME_CONF_PATH); let path = Path::new(Self::SCHEME_CONF_PATH);
let mut scheme = Base16Scheme::by_name(ThemeHandler::DEFAULT_SCHEME).unwrap(); let mut scheme = Base16Scheme::by_name(Self::DEFAULT_SCHEME).unwrap();
if path.exists() { if path.exists() {
if let Ok(scheme_name) = fs::read_to_string(path) { if let Ok(scheme_name) = fs::read_to_string(path) {
if let Some(sch) = Base16Scheme::by_name(&scheme_name) { if let Some(sch) = Base16Scheme::by_name(&scheme_name) {
@ -79,7 +79,7 @@ impl ThemeHandler {
} }
} }
} }
ThemeHandler::generate_base16_theme(scheme) Self::generate_base16_theme(scheme)
} }
} }
@ -91,7 +91,7 @@ impl ThemeChooser {
pub fn open(s: &mut Cursive) { pub fn open(s: &mut Cursive) {
let initial = ThemeHandler::load_base16_scheme(); let initial = ThemeHandler::load_base16_scheme();
let chooser = ThemeChooser::new(initial, |s,v| { let chooser = Self::new(initial, |s,v| {
ThemeHandler::save_base16_theme(v); ThemeHandler::save_base16_theme(v);
let theme = ThemeHandler::generate_base16_theme(v); let theme = ThemeHandler::generate_base16_theme(v);
s.set_theme(theme); s.set_theme(theme);
@ -99,11 +99,11 @@ impl ThemeChooser {
s.add_layer(chooser.with_id("theme-chooser")); s.add_layer(chooser.with_id("theme-chooser"));
} }
pub fn new<F>(initial: Option<Base16Scheme>, cb: F) -> ThemeChooser pub fn new<F>(initial: Option<Base16Scheme>, cb: F) -> Self
where F: 'static + Fn(&mut Cursive, &Base16Scheme) where F: 'static + Fn(&mut Cursive, &Base16Scheme)
{ {
let select = ThemeChooser::create_tree_view(initial.clone(), cb); let select = Self::create_tree_view(initial.clone(), cb);
let content = ThemeChooser::create_content(initial, select); let content = Self::create_content(initial, select);
let inner = ViewBox::boxed(content); let inner = ViewBox::boxed(content);
ThemeChooser { inner } ThemeChooser { inner }
} }
@ -136,16 +136,16 @@ impl ThemeChooser {
where F: 'static + Fn(&mut Cursive, &Base16Scheme) where F: 'static + Fn(&mut Cursive, &Base16Scheme)
{ {
let mut tree = TreeView::new() let mut tree = TreeView::new()
.on_select(ThemeChooser::on_tree_select) .on_select(Self::on_tree_select)
.on_collapse(ThemeChooser::on_tree_collapse) .on_collapse(Self::on_tree_collapse)
.on_submit(move |s,idx| { .on_submit(move |s,idx| {
let item = ThemeChooser::call_on_tree(s, |v| v.borrow_item(idx).cloned()); let item = Self::call_on_tree(s, |v| v.borrow_item(idx).cloned());
if let Some(TreeItem::ColorScheme(ref scheme)) = item { if let Some(TreeItem::ColorScheme(ref scheme)) = item {
(cb)(s, scheme); (cb)(s, scheme);
} }
}); });
ThemeChooser::populate_tree(initial, &mut tree); Self::populate_tree(initial, &mut tree);
tree.with_id("theme-tree") tree.with_id("theme-tree")
} }
@ -154,7 +154,7 @@ impl ThemeChooser {
let mut category_rows = HashMap::new(); let mut category_rows = HashMap::new();
let mut last_row = 0; let mut last_row = 0;
for scheme in &schemes { for scheme in &schemes {
last_row = ThemeChooser::add_scheme_to_tree(initial.as_ref(), tree, last_row, scheme, &mut category_rows); last_row = Self::add_scheme_to_tree(initial.as_ref(), tree, last_row, scheme, &mut category_rows);
} }
} }
@ -165,7 +165,7 @@ impl ThemeChooser {
if let Some(category) = scheme.category() { if let Some(category) = scheme.category() {
let is_initial_category = initial.map(|sc| sc.category() == scheme.category()).unwrap_or(false); let is_initial_category = initial.map(|sc| sc.category() == scheme.category()).unwrap_or(false);
let category_row = ThemeChooser::get_category_row(!is_initial_category, tree, &mut last_row, category, category_rows); let category_row = Self::get_category_row(!is_initial_category, tree, &mut last_row, category, category_rows);
if let Some(new_row) = tree.insert_item(item, Placement::LastChild, category_row) { if let Some(new_row) = tree.insert_item(item, Placement::LastChild, category_row) {
if is_initial { if is_initial {
tree.set_selected_row(new_row); tree.set_selected_row(new_row);
@ -198,7 +198,7 @@ impl ThemeChooser {
fn on_tree_select(s: &mut Cursive, idx: usize) { fn on_tree_select(s: &mut Cursive, idx: usize) {
let selected = ThemeChooser::call_on_tree(s, |v| v.borrow_item(idx).cloned()); let selected = Self::call_on_tree(s, |v| v.borrow_item(idx).cloned());
if let Some(item) = selected { if let Some(item) = selected {
if let TreeItem::ColorScheme(scheme) = item { if let TreeItem::ColorScheme(scheme) = item {
@ -208,9 +208,9 @@ impl ThemeChooser {
} }
fn on_tree_collapse(s: &mut Cursive, row: usize, is_collapsed: bool, _: usize) { fn on_tree_collapse(s: &mut Cursive, row: usize, is_collapsed: bool, _: usize) {
ThemeChooser::call_on_tree(s, |v| { Self::call_on_tree(s, |v| {
if let Some(item) = v.borrow_item_mut(row) { if let Some(item) = v.borrow_item_mut(row) {
if let &mut TreeItem::Category(ref _name, ref mut collapsed) = item { if let TreeItem::Category(ref _name, ref mut collapsed) = *item {
*collapsed = is_collapsed; *collapsed = is_collapsed;
} }
} }
@ -227,9 +227,9 @@ impl ThemeChooser {
fn toggle_expand_item(&self) -> EventResult { fn toggle_expand_item(&self) -> EventResult {
EventResult::with_cb(|s| { EventResult::with_cb(|s| {
ThemeChooser::call_on_tree(s, |v| { Self::call_on_tree(s, |v| {
if let Some(row) = v.row() { if let Some(row) = v.row() {
ThemeChooser::toggle_item_collapsed(v, row); Self::toggle_item_collapsed(v, row);
} }
}) })
}) })

View File

@ -570,7 +570,7 @@ impl<T: Display + Debug + 'static> View for TreeView<T> {
} }
fn important_area(&self, size: Vec2) -> Rect { fn important_area(&self, size: Vec2) -> Rect {
self.row().map(|i| Rect::from_size((0,i), (size.x, 1))).unwrap_or(Rect::from((0,0))) self.row().map(|i| Rect::from_size((0,i), (size.x, 1))).unwrap_or_else(|| Rect::from((0,0)))
} }
} }

View File

@ -15,9 +15,8 @@ pub fn main(args: Vec<String>) {
Logger::set_log_level(LogLevel::Info); Logger::set_log_level(LogLevel::Info);
} }
let command = args.iter().skip(1).next();
let result = match command { let result = match args.get(1) {
Some(s) if s == "rootfs" => do_rootfs(), Some(s) if s == "rootfs" => do_rootfs(),
Some(s) if s == "setup" => do_setup(), Some(s) if s == "setup" => do_setup(),
Some(s) if s == "start-realms" => do_start_realms(), Some(s) if s == "start-realms" => do_start_realms(),
@ -48,10 +47,8 @@ fn setup_keyring() -> Result<()> {
fn do_setup() -> Result<()> { fn do_setup() -> Result<()> {
if CommandLine::live_mode() || CommandLine::install_mode() { if CommandLine::live_mode() || CommandLine::install_mode() {
live::live_setup()?; live::live_setup()?;
} else { } else if let Err(err) = setup_keyring() {
if let Err(err) = setup_keyring() { warn!("Failed to setup keyring: {}", err);
warn!("Failed to setup keyring: {}", err);
}
} }
ResourceImage::mount_image_type("kernel")?; ResourceImage::mount_image_type("kernel")?;

View File

@ -89,7 +89,7 @@ fn choose_boot_partiton(scan: bool) -> Result<Partition> {
for p in partitions { for p in partitions {
best = compare_boot_partitions(best, p); best = compare_boot_partitions(best, p);
} }
best.ok_or(format_err!("No partition found to boot from")) best.ok_or_else(|| format_err!("No partition found to boot from"))
} }
fn compare_boot_partitions(a: Option<Partition>, b: Partition) -> Option<Partition> { fn compare_boot_partitions(a: Option<Partition>, b: Partition) -> Option<Partition> {

View File

@ -91,8 +91,8 @@ fn choose_disk() -> Result<Option<Disk>> {
fn prompt_choose_disk(disks: &[Disk]) -> Result<()> { fn prompt_choose_disk(disks: &[Disk]) -> Result<()> {
println!("Available disks:\n"); println!("Available disks:\n");
for idx in 0..disks.len() { for (idx,disk) in disks.iter().enumerate() {
println!(" [{}]: {} Size: {} Model: {}", idx + 1, disks[idx].path().display(), disks[idx].size_str(), disks[idx].model()); println!(" [{}]: {} Size: {} Model: {}", idx + 1, disk.path().display(), disk.size_str(), disk.model());
} }
print!("\nChoose a disk to install to (q to quit): "); print!("\nChoose a disk to install to (q to quit): ");
io::stdout().flush()?; io::stdout().flush()?;

View File

@ -490,7 +490,7 @@ impl Installer {
fn kernel_imagename(&self) -> String { fn kernel_imagename(&self) -> String {
let utsname = UtsName::uname(); let utsname = UtsName::uname();
let v = utsname.release().split("-").collect::<Vec<_>>(); let v = utsname.release().split('-').collect::<Vec<_>>();
format!("citadel-kernel-{}.img", v[0]) format!("citadel-kernel-{}.img", v[0])
} }

View File

@ -48,7 +48,7 @@ fn main() {
} }
fn dispatch_command(args: Vec<String>) { fn dispatch_command(args: Vec<String>) {
if let Some(command) = args.iter().skip(1).next() { if let Some(command) = args.get(1) {
match command.as_str() { match command.as_str() {
"boot" => boot::main(rebuild_args("citadel-boot", args)), "boot" => boot::main(rebuild_args("citadel-boot", args)),
"install" => install::main(rebuild_args("citadel-install", args)), "install" => install::main(rebuild_args("citadel-install", args)),

View File

@ -8,7 +8,7 @@ mod build;
pub fn main(args: Vec<String>) { pub fn main(args: Vec<String>) {
let config_path = match args.iter().skip(1).next() { let config_path = match args.get(1) {
Some(arg) => arg, Some(arg) => arg,
None => { None => {
println!("Expected config file argument"); println!("Expected config file argument");

View File

@ -124,7 +124,7 @@ fn image_info(arg_matches: &ArgMatches) -> Result<()> {
fn parse_resize_size(s: &str) -> Result<ResizeSize> { fn parse_resize_size(s: &str) -> Result<ResizeSize> {
let unit = s.chars().last().filter(|c| c.is_alphabetic()); let unit = s.chars().last().filter(|c| c.is_alphabetic());
let skip = if s.starts_with("+") { 1 } else { 0 }; let skip = if s.starts_with('+') { 1 } else { 0 };
let size = s.chars() let size = s.chars()
.skip(skip) .skip(skip)
.take_while(|c| c.is_numeric()) .take_while(|c| c.is_numeric())
@ -149,7 +149,7 @@ fn resize(arg_matches: &ArgMatches) -> Result<()> {
}; };
info!("Size is {}", size_arg); info!("Size is {}", size_arg);
let mode_add = size_arg.starts_with("+"); let mode_add = size_arg.starts_with('+');
let size = parse_resize_size(size_arg)?; let size = parse_resize_size(size_arg)?;
if mode_add { if mode_add {

View File

@ -129,7 +129,7 @@ impl DesktopFile {
pub fn add_action_line(&mut self, action: &str, line: Line) { pub fn add_action_line(&mut self, action: &str, line: Line) {
if line.is_key_value_type() { if line.is_key_value_type() {
let idx = self.lines.len(); let idx = self.lines.len();
let map = self.groups.entry(action.to_string()).or_insert(HashMap::new()); let map = self.groups.entry(action.to_string()).or_insert_with(HashMap::new);
map.insert(line.get_key_string(), idx); map.insert(line.get_key_string(), idx);
} }
self.lines.push(line); self.lines.push(line);

View File

@ -38,7 +38,7 @@ impl IconCache {
key.bytes().fold(0u32, |h, b| key.bytes().fold(0u32, |h, b|
(h << 5) (h << 5)
.wrapping_sub(h) .wrapping_sub(h)
.wrapping_add(b as u32)) .wrapping_add(u32::from(b)))
} }
fn read_string(&self, offset: usize) -> Result<String> { fn read_string(&self, offset: usize) -> Result<String> {

View File

@ -80,10 +80,8 @@ impl IconSync {
for entry in fs::read_dir(&base)? { for entry in fs::read_dir(&base)? {
let entry = entry?; let entry = entry?;
let apps = entry.path().join("apps"); let apps = entry.path().join("apps");
if apps.exists() { if apps.exists() && self.search_subdirectory(&base, &apps, icon_name)? {
if self.search_subdirectory(&base, &apps, icon_name)? { found = true;
found = true;
}
} }
} }
if found { if found {

View File

@ -2,11 +2,11 @@ use libcitadel::{Result, Logger, LogLevel};
mod desktop_file; mod desktop_file;
mod parser; mod parser;
mod sync; mod desktop_sync;
mod icons; mod icons;
mod icon_cache; mod icon_cache;
use self::sync::DesktopFileSync; use self::desktop_sync::DesktopFileSync;
pub fn main(args: Vec<String>) { pub fn main(args: Vec<String>) {

View File

@ -108,7 +108,7 @@ impl DesktopFileParser {
if let Line::KeyValue(ref k, ref value) = line { if let Line::KeyValue(ref k, ref value) = line {
if k == "Actions" { if k == "Actions" {
for s in value.split_terminator(";") { for s in value.split_terminator(';') {
self.known_actions.insert(s.trim().to_string()); self.known_actions.insert(s.trim().to_string());
} }
} }
@ -152,7 +152,7 @@ impl DesktopFileParser {
} }
} }
const DESKTOP_ACTION: &'static str = "Desktop Action "; const DESKTOP_ACTION: &str = "Desktop Action ";
struct LineParser<'a> { struct LineParser<'a> {
s: &'a str, s: &'a str,
@ -202,17 +202,17 @@ impl <'a> LineParser<'a> {
} else if content == "Desktop Entry" { } else if content == "Desktop Entry" {
return Some(Line::DesktopHeader) return Some(Line::DesktopHeader)
} }
return Some(Line::GroupHeader(content.to_string())) Some(Line::GroupHeader(content.to_string()))
} }
fn parse_keyval(&self) -> Option<Line> { fn parse_keyval(&self) -> Option<Line> {
let parts: Vec<&str> = self.s.splitn(2, "=").collect(); let parts: Vec<&str> = self.s.splitn(2, '=').collect();
if parts.len() != 2 { if parts.len() != 2 {
return None return None
} }
let key = parts[0].trim(); let key = parts[0].trim();
let val = parts[1].trim(); let val = parts[1].trim();
if !key.contains("[") { if !key.contains('[') {
if key == "Exec" { if key == "Exec" {
return Some(Line::ExecLine(val.to_string())) return Some(Line::ExecLine(val.to_string()))
} }
@ -222,7 +222,7 @@ impl <'a> LineParser<'a> {
} }
fn parse_locale(&self, key: &str) -> Option<(String,String)> { fn parse_locale(&self, key: &str) -> Option<(String,String)> {
let idx = key.find("[").unwrap(); let idx = key.find('[').unwrap();
let (k,loc) = key.split_at(idx); let (k,loc) = key.split_at(idx);
let mut chars = loc.chars(); let mut chars = loc.chars();
if let Some(']') = chars.next_back() { if let Some(']') = chars.next_back() {

View File

@ -38,40 +38,40 @@ impl CommandLine {
/// Return `true` if variable citadel.noverity is present on kernel command line. /// Return `true` if variable citadel.noverity is present on kernel command line.
pub fn noverity() -> bool { pub fn noverity() -> bool {
CommandLine::var_exists("citadel.noverity") Self::var_exists("citadel.noverity")
} }
pub fn nosignatures() -> bool { pub fn nosignatures() -> bool {
CommandLine::var_exists("citadel.nosignatures") Self::var_exists("citadel.nosignatures")
} }
/// Return `true` if variable citadel.install is present on kernel command line. /// Return `true` if variable citadel.install is present on kernel command line.
pub fn install_mode() -> bool { pub fn install_mode() -> bool {
CommandLine::var_exists("citadel.install") Self::var_exists("citadel.install")
} }
/// Return `true` if variable citadel.live is present on kernel command line. /// Return `true` if variable citadel.live is present on kernel command line.
pub fn live_mode() -> bool { pub fn live_mode() -> bool {
CommandLine::var_exists("citadel.live") Self::var_exists("citadel.live")
} }
/// Return `true` if variable citadel.recovery is present on kernel command line. /// Return `true` if variable citadel.recovery is present on kernel command line.
pub fn recovery_mode() -> bool { pub fn recovery_mode() -> bool {
CommandLine::var_exists("citadel.recovery") Self::var_exists("citadel.recovery")
} }
pub fn overlay() -> bool { CommandLine::var_exists("citadel.overlay") } pub fn overlay() -> bool { Self::var_exists("citadel.overlay") }
/// Return `true` if sealed realmfs images are enabled on kernel command line /// Return `true` if sealed realmfs images are enabled on kernel command line
pub fn sealed() -> bool { CommandLine::var_exists("citadel.sealed") } pub fn sealed() -> bool { Self::var_exists("citadel.sealed") }
pub fn channel() -> Option<&'static str> { pub fn channel() -> Option<&'static str> {
CommandLine::get_value("citadel.channel") Self::get_value("citadel.channel")
} }
fn _channel() -> Option<(&'static str,Option<&'static str>)> { fn _channel() -> Option<(&'static str,Option<&'static str>)> {
if let Some(channel) = CommandLine::channel() { if let Some(channel) = Self::channel() {
let parts = channel.splitn(2, ":").collect::<Vec<_>>(); let parts = channel.splitn(2, ':').collect::<Vec<_>>();
if parts.len() == 2 { if parts.len() == 2 {
return Some((parts[0], Some(parts[1]))) return Some((parts[0], Some(parts[1])))
} }
@ -82,33 +82,33 @@ impl CommandLine {
} }
pub fn channel_name() -> Option<&'static str> { pub fn channel_name() -> Option<&'static str> {
if let Some((name, _)) = CommandLine::_channel() { if let Some((name, _)) = Self::_channel() {
return Some(name) return Some(name)
} }
None None
} }
pub fn channel_pubkey() -> Option<&'static str> { pub fn channel_pubkey() -> Option<&'static str> {
if let Some((_, pubkey)) = CommandLine::_channel() { if let Some((_, pubkey)) = Self::_channel() {
return pubkey return pubkey
} }
None None
} }
pub fn verbose() -> bool { pub fn verbose() -> bool {
CommandLine::var_exists("citadel.verbose") Self::var_exists("citadel.verbose")
} }
pub fn debug() -> bool { pub fn debug() -> bool {
CommandLine::var_exists("citadel.debug") Self::var_exists("citadel.debug")
} }
fn new() -> CommandLine { fn new() -> Self {
CommandLine{ varmap: HashMap::new() } CommandLine{ varmap: HashMap::new() }
} }
fn load() -> Result<CommandLine> { fn load() -> Result<Self> {
let s = fs::read_to_string("/proc/cmdline")?; let s = fs::read_to_string("/proc/cmdline")?;
let varmap = CommandLineParser::new(s).parse(); let varmap = CommandLineParser::new(s).parse();
Ok(CommandLine{varmap}) Ok(CommandLine{varmap})
@ -157,7 +157,7 @@ struct CommandLineParser {
} }
impl CommandLineParser { impl CommandLineParser {
fn new(cmdline: String) -> CommandLineParser { fn new(cmdline: String) -> Self {
CommandLineParser { CommandLineParser {
cmdline, cmdline,
varmap: HashMap::new(), varmap: HashMap::new(),

View File

@ -30,7 +30,7 @@ pub struct Exec {
} }
impl Exec { impl Exec {
pub fn new(cmd: impl AsRef<str>) -> Exec { pub fn new(cmd: impl AsRef<str>) -> Self {
Exec { Exec {
cmd_name: cmd.as_ref().to_string(), cmd_name: cmd.as_ref().to_string(),
cmd: Command::new(cmd.as_ref()), cmd: Command::new(cmd.as_ref()),
@ -55,7 +55,7 @@ impl Exec {
for line in BufReader::new(result.stderr.as_slice()).lines() { for line in BufReader::new(result.stderr.as_slice()).lines() {
verbose!(" {}", line?); verbose!(" {}", line?);
} }
self.check_cmd_status(&result.status) self.check_cmd_status(result.status)
} }
@ -73,7 +73,7 @@ impl Exec {
self.ensure_command_exists()?; self.ensure_command_exists()?;
self.add_args(args.as_ref()); self.add_args(args.as_ref());
let result = self.cmd.stderr(Stdio::inherit()).output()?; let result = self.cmd.stderr(Stdio::inherit()).output()?;
self.check_cmd_status(&result.status)?; self.check_cmd_status(result.status)?;
Ok(String::from_utf8(result.stdout).unwrap().trim().to_owned()) Ok(String::from_utf8(result.stdout).unwrap().trim().to_owned())
} }
@ -103,7 +103,7 @@ impl Exec {
self.cmd.args(args); self.cmd.args(args);
} }
fn check_cmd_status(&self, status: &ExitStatus) -> Result<()> { fn check_cmd_status(&self, status: ExitStatus) -> Result<()> {
if !status.success() { if !status.success() {
match status.code() { match status.code() {
Some(code) => bail!("command {} failed with exit code: {}", self.cmd_name, code), Some(code) => bail!("command {} failed with exit code: {}", self.cmd_name, code),
@ -116,7 +116,7 @@ impl Exec {
fn ensure_command_exists(&self) -> Result<()> { fn ensure_command_exists(&self) -> Result<()> {
let path = Path::new(&self.cmd_name); let path = Path::new(&self.cmd_name);
if !path.is_absolute() { if !path.is_absolute() {
Exec::search_path(&self.cmd_name)?; Self::search_path(&self.cmd_name)?;
return Ok(()) return Ok(())
} else if path.exists() { } else if path.exists() {
return Ok(()) return Ok(())
@ -148,13 +148,13 @@ fn ranged_reader<P: AsRef<Path>>(path: P, range: FileRange) -> Result<Box<dyn Re
let offset = match range { let offset = match range {
FileRange::All => 0, FileRange::All => 0,
FileRange::Offset(n) => n, FileRange::Offset(n) => n,
FileRange::Range {offset, len: _} => offset, FileRange::Range {offset, ..} => offset,
}; };
if offset > 0 { if offset > 0 {
f.seek(SeekFrom::Start(offset as u64))?; f.seek(SeekFrom::Start(offset as u64))?;
} }
let r = BufReader::new(f); let r = BufReader::new(f);
if let FileRange::Range {offset: _, len} = range { if let FileRange::Range {len, ..} = range {
Ok(Box::new(r.take(len as u64))) Ok(Box::new(r.take(len as u64)))
} else { } else {
Ok(Box::new(r)) Ok(Box::new(r))

View File

@ -101,8 +101,8 @@ impl HeaderBytes {
} }
fn read_u16(&self, idx: usize) -> u16 { fn read_u16(&self, idx: usize) -> u16 {
let hi = self.read_u8(idx) as u16; let hi = u16::from(self.read_u8(idx));
let lo = self.read_u8(idx + 1) as u16; let lo = u16::from(self.read_u8(idx + 1));
(hi << 8) | lo (hi << 8) | lo
} }
@ -152,11 +152,8 @@ impl ImageHeader {
/// Size of header block /// Size of header block
pub const HEADER_SIZE: usize = 4096; pub const HEADER_SIZE: usize = 4096;
pub fn new() -> ImageHeader { pub fn new() -> Self {
let metainfo = Mutex::new(None); Self::default()
let buffer = HeaderBytes::create_empty();
let timestamp = AtomicIsize::new(0);
ImageHeader { buffer, metainfo, timestamp }
} }
/// Reload header if file has changed on disk /// Reload header if file has changed on disk
@ -184,14 +181,14 @@ impl ImageHeader {
Ok(()) Ok(())
} }
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<ImageHeader> { pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let path = path.as_ref(); let path = path.as_ref();
let (size,ts) = Self::file_metadata(path)?; let (size,ts) = Self::file_metadata(path)?;
if size < Self::HEADER_SIZE { if size < Self::HEADER_SIZE {
bail!("Cannot load image header because {} has a size of {}", path.display(), size); bail!("Cannot load image header because {} has a size of {}", path.display(), size);
} }
let mut f = File::open(path)?; let mut f = File::open(path)?;
let mut header = ImageHeader::from_reader(&mut f)?; let mut header = Self::from_reader(&mut f)?;
*header.timestamp.get_mut() = ts; *header.timestamp.get_mut() = ts;
Ok(header) Ok(header)
} }
@ -202,14 +199,14 @@ impl ImageHeader {
Ok((metadata.len() as usize, metadata.mtime() as isize)) Ok((metadata.len() as usize, metadata.mtime() as isize))
} }
pub fn from_reader<R: Read>(r: &mut R) -> Result<ImageHeader> { pub fn from_reader<R: Read>(r: &mut R) -> Result<Self> {
let mut v = vec![0u8; ImageHeader::HEADER_SIZE]; let mut v = vec![0u8; Self::HEADER_SIZE];
r.read_exact(&mut v)?; r.read_exact(&mut v)?;
Self::from_slice(&v) Self::from_slice(&v)
} }
fn from_slice(slice: &[u8]) -> Result<ImageHeader> { fn from_slice(slice: &[u8]) -> Result<Self> {
assert_eq!(slice.len(), ImageHeader::HEADER_SIZE); assert_eq!(slice.len(), Self::HEADER_SIZE);
let buffer = HeaderBytes::create_from_slice(slice); let buffer = HeaderBytes::create_from_slice(slice);
let metainfo = Mutex::new(None); let metainfo = Mutex::new(None);
let timestamp = AtomicIsize::new(0); let timestamp = AtomicIsize::new(0);
@ -218,7 +215,7 @@ impl ImageHeader {
Ok(header) Ok(header)
} }
pub fn from_partition<P: AsRef<Path>>(path: P) -> Result<ImageHeader> { pub fn from_partition<P: AsRef<Path>>(path: P) -> Result<Self> {
let mut dev = BlockDev::open_ro(path.as_ref())?; let mut dev = BlockDev::open_ro(path.as_ref())?;
let nsectors = dev.nsectors()?; let nsectors = dev.nsectors()?;
ensure!( ensure!(
@ -227,7 +224,7 @@ impl ImageHeader {
path.as_ref().display(), path.as_ref().display(),
nsectors nsectors
); );
let mut buffer = AlignedBuffer::new(ImageHeader::HEADER_SIZE); let mut buffer = AlignedBuffer::new(Self::HEADER_SIZE);
dev.read_sectors(nsectors - 8, buffer.as_mut())?; dev.read_sectors(nsectors - 8, buffer.as_mut())?;
Self::from_slice(buffer.as_ref()) Self::from_slice(buffer.as_ref())
} }
@ -276,7 +273,7 @@ impl ImageHeader {
let mut lock = self.metainfo.lock().unwrap(); let mut lock = self.metainfo.lock().unwrap();
let mb = self.metainfo_bytes(); let mb = self.metainfo_bytes();
let metainfo = MetaInfo::parse_bytes(&mb) let metainfo = MetaInfo::parse_bytes(&mb)
.ok_or(format_err!("ImageHeader has invalid metainfo"))?; .ok_or_else(|| format_err!("ImageHeader has invalid metainfo"))?;
*lock = Some(Arc::new(metainfo)); *lock = Some(Arc::new(metainfo));
Ok(()) Ok(())
} }
@ -338,7 +335,7 @@ impl ImageHeader {
pub fn set_metainfo_bytes(&self, bytes: &[u8]) -> Result<()> { pub fn set_metainfo_bytes(&self, bytes: &[u8]) -> Result<()> {
let metainfo = MetaInfo::parse_bytes(bytes) let metainfo = MetaInfo::parse_bytes(bytes)
.ok_or(format_err!("Could not parse metainfo bytes as valid metainfo document"))?; .ok_or_else(|| format_err!("Could not parse metainfo bytes as valid metainfo document"))?;
let mut lock = self.metainfo.lock().unwrap(); let mut lock = self.metainfo.lock().unwrap();
self.with_bytes_mut(|bs| { self.with_bytes_mut(|bs| {
@ -418,6 +415,14 @@ impl ImageHeader {
} }
} }
impl Default for ImageHeader {
fn default() -> Self {
let metainfo = Mutex::new(None);
let buffer = HeaderBytes::create_empty();
let timestamp = AtomicIsize::new(0);
ImageHeader { buffer, metainfo, timestamp }
}
}
#[derive(Deserialize, Serialize, Clone, Default)] #[derive(Deserialize, Serialize, Clone, Default)]
pub struct MetaInfo { pub struct MetaInfo {

View File

@ -29,14 +29,14 @@ pub struct KeyRing {
} }
impl KeyRing { impl KeyRing {
pub fn create_new() -> KeyRing { pub fn create_new() -> Self {
let seed = KeyRing::new_random_seed(); let seed = Self::new_random_seed();
let mut keypairs = HashMap::new(); let mut keypairs = HashMap::new();
keypairs.insert("realmfs-user".to_string(), hex::encode(&seed.0)); keypairs.insert("realmfs-user".to_string(), hex::encode(&seed.0));
KeyRing { keypairs } KeyRing { keypairs }
} }
pub fn load<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<KeyRing> { pub fn load<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<Self> {
let mut sbox = SecretBox::new(path.as_ref()); let mut sbox = SecretBox::new(path.as_ref());
sbox.read().map_err(|e| format_err!("Error reading keyring file: {}", e))?; sbox.read().map_err(|e| format_err!("Error reading keyring file: {}", e))?;
let mut bytes = sbox.open(passphrase)?; let mut bytes = sbox.open(passphrase)?;
@ -45,13 +45,13 @@ impl KeyRing {
Ok(keyring) Ok(keyring)
} }
pub fn load_with_cryptsetup_passphrase<P: AsRef<Path>>(path: P) -> Result<KeyRing> { pub fn load_with_cryptsetup_passphrase<P: AsRef<Path>>(path: P) -> Result<Self> {
let passphrase = KeyRing::get_cryptsetup_passphrase()?; let passphrase = Self::get_cryptsetup_passphrase()?;
KeyRing::load(path, &passphrase) Self::load(path, &passphrase)
} }
fn get_cryptsetup_passphrase() -> Result<String> { fn get_cryptsetup_passphrase() -> Result<String> {
let key = KeyRing::get_key("cryptsetup")?; let key = Self::get_key("cryptsetup")?;
info!("Got key {}", key.0); info!("Got key {}", key.0);
let buf = key.read()?; let buf = key.read()?;
match buf.split(|b| *b == 0).map(|bs| String::from_utf8_lossy(bs).to_string()).last() { match buf.split(|b| *b == 0).map(|bs| String::from_utf8_lossy(bs).to_string()).last() {
@ -73,7 +73,7 @@ impl KeyRing {
info!("Found {} key with request_key", name); info!("Found {} key with request_key", name);
return Ok(key); return Ok(key);
} }
return Err(format_err!("kernel key '{}' not found", name)) Err(format_err!("kernel key '{}' not found", name))
} }
pub fn add_keys_to_kernel(&self) -> Result<()> { pub fn add_keys_to_kernel(&self) -> Result<()> {
@ -81,13 +81,13 @@ impl KeyRing {
info!("Adding {} to kernel keystore", k.as_str()); info!("Adding {} to kernel keystore", k.as_str());
let bytes = hex::decode(v)?; let bytes = hex::decode(v)?;
let key = KernelKey::add_key("user", k.as_str(), &bytes, KEY_SPEC_USER_KEYRING)?; let key = KernelKey::add_key("user", k.as_str(), &bytes, KEY_SPEC_USER_KEYRING)?;
key.set_perm(0x3f030000)?; key.set_perm(0x3f03_0000)?;
} }
Ok(()) Ok(())
} }
pub fn get_kernel_keypair(name: &str) -> Result<KeyPair> { pub fn get_kernel_keypair(name: &str) -> Result<KeyPair> {
let key = KeyRing::get_key(name)?; let key = Self::get_key(name)?;
let data = key.read()?; let data = key.read()?;
KeyPair::from_bytes(&data) KeyPair::from_bytes(&data)
} }
@ -130,7 +130,7 @@ struct SecretBox {
} }
impl SecretBox { impl SecretBox {
fn new(path: &Path) -> SecretBox { fn new(path: &Path) -> Self {
SecretBox { SecretBox {
path: path.to_path_buf(), path: path.to_path_buf(),
salt: Salt([0; SALTBYTES]), salt: Salt([0; SALTBYTES]),
@ -151,7 +151,7 @@ impl SecretBox {
} }
fn open(&self, passphrase: &str) -> Result<Vec<u8>> { fn open(&self, passphrase: &str) -> Result<Vec<u8>> {
let key = SecretBox::passphrase_to_key(passphrase, &self.salt)?; let key = Self::passphrase_to_key(passphrase, &self.salt)?;
let result = secretbox::open(&self.data, &self.nonce, &key) let result = secretbox::open(&self.data, &self.nonce, &key)
.map_err(|_| format_err!("Failed to decrypt {}", self.path.display()))?; .map_err(|_| format_err!("Failed to decrypt {}", self.path.display()))?;
Ok(result) Ok(result)
@ -180,31 +180,31 @@ pub struct KernelKey(int32_t);
impl KernelKey { impl KernelKey {
pub fn user_keyring() -> KernelKey { pub fn user_keyring() -> Self {
KernelKey(KEY_SPEC_USER_KEYRING) KernelKey(KEY_SPEC_USER_KEYRING)
} }
pub fn request_key(key_type: &str, description: &str) -> Result<KernelKey> { pub fn request_key(key_type: &str, description: &str) -> Result<Self> {
let key_type = CString::new(key_type).unwrap(); let key_type = CString::new(key_type).unwrap();
let description = CString::new(description).unwrap(); let description = CString::new(description).unwrap();
let serial = _request_key(key_type.as_ptr(), description.as_ptr())?; let serial = _request_key(key_type.as_ptr(), description.as_ptr())?;
Ok(KernelKey(serial as i32)) Ok(KernelKey(serial as i32))
} }
pub fn add_key(key_type: &str, description: &str, payload: &[u8], ring_id: c_int) -> Result<KernelKey> { pub fn add_key(key_type: &str, description: &str, payload: &[u8], ring_id: c_int) -> Result<Self> {
let key_type = CString::new(key_type).unwrap(); let key_type = CString::new(key_type).unwrap();
let description = CString::new(description).unwrap(); let description = CString::new(description).unwrap();
let serial = _add_key(key_type.as_ptr(), description.as_ptr(), payload.as_ptr(), payload.len(), ring_id)?; let serial = _add_key(key_type.as_ptr(), description.as_ptr(), payload.as_ptr(), payload.len(), ring_id)?;
Ok(KernelKey(serial as i32)) Ok(KernelKey(serial as i32))
} }
pub fn get_keyring_id(&self, create: bool) -> Result<KernelKey> { pub fn get_keyring_id(&self, create: bool) -> Result<Self> {
let serial = keyctl2(KEYCTL_GET_KEYRING_ID, self.id(), create as u64)?; let serial = keyctl2(KEYCTL_GET_KEYRING_ID, self.id(), create as u64)?;
Ok(KernelKey(serial as i32)) Ok(KernelKey(serial as i32))
} }
pub fn set_perm(&self, perm: u32) -> Result<()> { pub fn set_perm(&self, perm: u32) -> Result<()> {
keyctl2(KEYCTL_SETPERM, self.id(), perm as u64)?; keyctl2(KEYCTL_SETPERM, self.id(), u64::from(perm))?;
Ok(()) Ok(())
} }
@ -219,7 +219,7 @@ impl KernelKey {
} }
} }
pub fn search(&self, description: &str) -> Result<KernelKey> { pub fn search(&self, description: &str) -> Result<Self> {
let key_type = CString::new("user").unwrap(); let key_type = CString::new("user").unwrap();
let description = CString::new(description).unwrap(); let description = CString::new(description).unwrap();

View File

@ -72,8 +72,8 @@ impl Logger {
logger.log_message(level, message.as_ref()); logger.log_message(level, message.as_ref());
} }
fn new() -> Logger { fn new() -> Self {
Logger { level: LogLevel::Notice, output: Box::new(DefaultLogOutput) } Self { level: LogLevel::Notice, output: Box::new(DefaultLogOutput) }
} }
fn log_message(&mut self, level: LogLevel, message: &str) { fn log_message(&mut self, level: LogLevel, message: &str) {
@ -96,11 +96,11 @@ impl Logger {
} }
} }
#[derive(Clone)] #[derive(Clone,Default)]
pub struct DefaultLogOutput; pub struct DefaultLogOutput;
impl DefaultLogOutput { impl DefaultLogOutput {
pub fn new() -> Self { DefaultLogOutput } pub fn new() -> Self { DefaultLogOutput::default() }
} }
impl LogOutput for DefaultLogOutput { impl LogOutput for DefaultLogOutput {

View File

@ -18,19 +18,19 @@ struct HeaderInfo {
} }
impl Partition { impl Partition {
pub fn rootfs_partitions() -> Result<Vec<Partition>> { pub fn rootfs_partitions() -> Result<Vec<Self>> {
let mut v = Vec::new(); let mut v = Vec::new();
for path in rootfs_partition_paths()? { for path in rootfs_partition_paths()? {
let partition = Partition::load(&path)?; let partition = Self::load(&path)?;
v.push(partition); v.push(partition);
} }
v.sort_unstable_by(|a,b| a.path().cmp(b.path())); v.sort_unstable_by(|a,b| a.path().cmp(b.path()));
Ok(v) Ok(v)
} }
fn load(dev: &Path) -> Result<Partition> { fn load(dev: &Path) -> Result<Self> {
let is_mounted = is_in_use(dev)?; let is_mounted = is_in_use(dev)?;
let header = Partition::load_header(dev)?; let header = Self::load_header(dev)?;
Ok(Partition::new(dev, header, is_mounted)) Ok(Partition::new(dev, header, is_mounted))
} }
@ -55,7 +55,7 @@ impl Partition {
})) }))
} }
fn new(path: &Path, hinfo: Option<HeaderInfo>, is_mounted: bool) -> Partition { fn new(path: &Path, hinfo: Option<HeaderInfo>, is_mounted: bool) -> Self {
Partition { Partition {
path: path.to_owned(), path: path.to_owned(),
hinfo, is_mounted, hinfo, is_mounted,

View File

@ -24,7 +24,7 @@ pub enum OverlayType {
} }
impl OverlayType { impl OverlayType {
pub fn from_str_value(value: &str) -> OverlayType { pub fn from_str_value(value: &str) -> Self {
if value == "tmpfs" { if value == "tmpfs" {
OverlayType::TmpFS OverlayType::TmpFS
} else if value == "storage" { } else if value == "storage" {
@ -35,7 +35,7 @@ impl OverlayType {
} }
} }
pub fn to_str_value(&self) -> Option<&'static str> { pub fn to_str_value(self) -> Option<&'static str> {
match self { match self {
OverlayType::None => None, OverlayType::None => None,
OverlayType::TmpFS => Some("tmpfs"), OverlayType::TmpFS => Some("tmpfs"),
@ -122,25 +122,25 @@ pub struct RealmConfig {
impl RealmConfig { impl RealmConfig {
/// Return an 'unloaded' realm config instance. /// Return an 'unloaded' realm config instance.
pub fn unloaded_realm_config(realm_name: &str) -> RealmConfig { pub fn unloaded_realm_config(realm_name: &str) -> Self {
let path = Path::new(Realms::BASE_PATH) let path = Path::new(Realms::BASE_PATH)
.join(format!("realm-{}", realm_name)) .join(format!("realm-{}", realm_name))
.join("config"); .join("config");
let mut config = RealmConfig::empty(); let mut config = Self::empty();
config.path = path; config.path = path;
config config
} }
fn load_global_config() -> RealmConfig { fn load_global_config() -> Self {
if let Some(mut global) = RealmConfig::load_config("/storage/realms/config") { if let Some(mut global) = Self::load_config("/storage/realms/config") {
global.parent = Some(Box::new(RealmConfig::default())); global.parent = Some(Box::new(Self::default()));
return global; return global;
} }
RealmConfig::default() Self::default()
} }
fn load_config<P: AsRef<Path>>(path: P) -> Option<RealmConfig> { fn load_config<P: AsRef<Path>>(path: P) -> Option<Self> {
if path.as_ref().exists() { if path.as_ref().exists() {
match fs::read_to_string(path.as_ref()) { match fs::read_to_string(path.as_ref()) {
Ok(s) => return toml::from_str::<RealmConfig>(&s).ok(), Ok(s) => return toml::from_str::<RealmConfig>(&s).ok(),
@ -177,7 +177,7 @@ impl RealmConfig {
let s = fs::read_to_string(&self.path)?; let s = fs::read_to_string(&self.path)?;
*self = toml::from_str(&s)?; *self = toml::from_str(&s)?;
} else { } else {
*self = RealmConfig::empty(); *self = Self::empty();
} }
self.path = path; self.path = path;
self.loaded = Some(self.read_mtime()); self.loaded = Some(self.read_mtime());
@ -185,7 +185,7 @@ impl RealmConfig {
Ok(()) Ok(())
} }
pub fn default() -> RealmConfig { pub fn default() -> Self {
RealmConfig { RealmConfig {
use_shared_dir: Some(true), use_shared_dir: Some(true),
use_ephemeral_home: Some(false), use_ephemeral_home: Some(false),
@ -215,7 +215,7 @@ impl RealmConfig {
} }
} }
pub fn empty() -> RealmConfig { pub fn empty() -> Self {
RealmConfig { RealmConfig {
use_shared_dir: None, use_shared_dir: None,
use_ephemeral_home: None, use_ephemeral_home: None,
@ -394,8 +394,7 @@ impl RealmConfig {
/// The type of overlay on root filesystem to set up for this realm. /// The type of overlay on root filesystem to set up for this realm.
pub fn overlay(&self) -> OverlayType { pub fn overlay(&self) -> OverlayType {
self.str_value(|c| c.overlay.as_ref()) self.str_value(|c| c.overlay.as_ref())
.map(OverlayType::from_str_value) .map_or(OverlayType::None, OverlayType::from_str_value)
.unwrap_or(OverlayType::None)
} }
/// Set the overlay string variable according to the `OverlayType` argument. /// Set the overlay string variable according to the `OverlayType` argument.

View File

@ -7,6 +7,7 @@ use std::thread::{self,JoinHandle};
use std::path; use std::path;
use crate::{RealmManager, Result, Realm}; use crate::{RealmManager, Result, Realm};
use super::realms::HasCurrentChanged;
use dbus::{Connection, BusType, ConnectionItem, Message, Path}; use dbus::{Connection, BusType, ConnectionItem, Message, Path};
use inotify::{Inotify, WatchMask, WatchDescriptor, Event}; use inotify::{Inotify, WatchMask, WatchDescriptor, Event};
@ -54,8 +55,8 @@ impl Inner {
} }
} }
fn set_manager(&mut self, manager: Arc<RealmManager>) { fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager); self.manager = Arc::downgrade(manager);
} }
pub fn add_handler<F>(&mut self, handler: F) pub fn add_handler<F>(&mut self, handler: F)
@ -96,7 +97,7 @@ impl RealmEventListener {
} }
} }
pub fn set_manager(&self, manager: Arc<RealmManager>) { pub fn set_manager(&self, manager: &Arc<RealmManager>) {
self.inner_mut().set_manager(manager); self.inner_mut().set_manager(manager);
} }
@ -242,7 +243,7 @@ impl DbusEventListener {
fn handle_signal(&self, message: Message) -> Result<()> { fn handle_signal(&self, message: Message) -> Result<()> {
let member = message.member() let member = message.member()
.ok_or(format_err!("invalid signal"))?; .ok_or_else(|| format_err!("invalid signal"))?;
let (name, _path): (String, Path) = message.read2()?; let (name, _path): (String, Path) = message.read2()?;
if let (Some(interface),Some(member)) = (message.interface(),message.member()) { if let (Some(interface),Some(member)) = (message.interface(),message.member()) {
verbose!("DBUS: {}:[{}({})]", interface, member,name); verbose!("DBUS: {}:[{}({})]", interface, member,name);
@ -343,7 +344,7 @@ impl InotifyEventListener {
fn handle_current_event(&self) { fn handle_current_event(&self) {
self.inner().with_manager(|m| { self.inner().with_manager(|m| {
if let Some(current) = m.has_current_changed() { if let HasCurrentChanged::Changed(current) = m.has_current_changed() {
self.inner().send_event(RealmEvent::Current(current)); self.inner().send_event(RealmEvent::Current(current));
} }
}) })

View File

@ -9,6 +9,7 @@ use crate::realmfs::realmfs_set::RealmFSSet;
use super::systemd::Systemd; use super::systemd::Systemd;
use super::network::NetworkConfig; use super::network::NetworkConfig;
use super::events::{RealmEventListener, RealmEvent}; use super::events::{RealmEventListener, RealmEvent};
use crate::realm::realms::HasCurrentChanged;
pub struct RealmManager { pub struct RealmManager {
inner: RwLock<Inner>, inner: RwLock<Inner>,
@ -38,25 +39,25 @@ impl RealmManager {
Ok(network) Ok(network)
} }
pub fn load() -> Result<Arc<RealmManager>> { pub fn load() -> Result<Arc<Self>> {
let inner = Inner::new()?; let inner = Inner::new()?;
let inner = RwLock::new(inner); let inner = RwLock::new(inner);
let network = RealmManager::create_network_config()?; let network = Self::create_network_config()?;
let systemd = Systemd::new(network); let systemd = Systemd::new(network);
let manager = RealmManager{ inner, systemd }; let manager = RealmManager{ inner, systemd };
let manager = Arc::new(manager); let manager = Arc::new(manager);
manager.set_manager(manager.clone()); manager.set_manager(&manager);
Ok(manager) Ok(manager)
} }
fn set_manager(&self, manager: Arc<RealmManager>) { fn set_manager(&self, manager: &Arc<RealmManager>) {
let mut inner = self.inner_mut(); let mut inner = self.inner_mut();
inner.events.set_manager(manager.clone()); inner.events.set_manager(manager);
inner.realms.set_manager(manager.clone()); inner.realms.set_manager(manager);
inner.realmfs_set.set_manager(manager); inner.realmfs_set.set_manager(manager);
} }
@ -102,7 +103,7 @@ impl RealmManager {
pub fn run_in_current<S: AsRef<str>>(args: &[S], use_launcher: bool) -> Result<()> { pub fn run_in_current<S: AsRef<str>>(args: &[S], use_launcher: bool) -> Result<()> {
let realm = Realms::load_current_realm() let realm = Realms::load_current_realm()
.ok_or(format_err!("Could not find current realm"))?; .ok_or_else(|| format_err!("Could not find current realm"))?;
if !realm.is_active() { if !realm.is_active() {
bail!("Current realm {} is not active?", realm.name()); bail!("Current realm {} is not active?", realm.name());
@ -130,8 +131,7 @@ impl RealmManager {
.into_iter() .into_iter()
.filter(|r| { .filter(|r| {
r.realmfs_mountpoint() r.realmfs_mountpoint()
.map(|mp| activation.is_mountpoint(&mp)) .map_or(false, |mp| activation.is_mountpoint(&mp))
.unwrap_or(false)
}) })
.collect() .collect()
} }
@ -150,7 +150,7 @@ impl RealmManager {
/// Notify `RealmManager` that `mountpoint` has been released by a /// Notify `RealmManager` that `mountpoint` has been released by a
/// `Realm`. /// `Realm`.
pub fn release_mountpoint(&self, mountpoint: Mountpoint) { pub fn release_mountpoint(&self, mountpoint: &Mountpoint) {
info!("releasing mountpoint: {}", mountpoint); info!("releasing mountpoint: {}", mountpoint);
if !mountpoint.is_valid() { if !mountpoint.is_valid() {
warn!("bad mountpoint {} passed to release_mountpoint()", mountpoint); warn!("bad mountpoint {} passed to release_mountpoint()", mountpoint);
@ -158,12 +158,12 @@ impl RealmManager {
} }
if let Some(realmfs) = self.realmfs_by_name(mountpoint.realmfs()) { if let Some(realmfs) = self.realmfs_by_name(mountpoint.realmfs()) {
if realmfs.release_mountpoint(&mountpoint) { if realmfs.release_mountpoint(mountpoint) {
return; return;
} }
} }
if let Some(activation) = Activation::for_mountpoint(&mountpoint) { if let Some(activation) = Activation::for_mountpoint(mountpoint) {
let active = self.active_mountpoints(); let active = self.active_mountpoints();
if let Err(e) = activation.deactivate(&active) { if let Err(e) = activation.deactivate(&active) {
warn!("error on detached deactivation for {}: {}",activation.device(), e); warn!("error on detached deactivation for {}: {}",activation.device(), e);
@ -308,7 +308,7 @@ impl RealmManager {
} }
} }
pub fn has_current_changed(&self) -> Option<Option<Realm>> { pub fn has_current_changed(&self) -> HasCurrentChanged {
self.inner_mut().realms.has_current_changed() self.inner_mut().realms.has_current_changed()
} }

View File

@ -3,6 +3,7 @@ pub(crate) mod overlay;
pub(crate) mod config; pub(crate) mod config;
pub(crate) mod realms; pub(crate) mod realms;
pub(crate) mod manager; pub(crate) mod manager;
#[allow(clippy::module_inception)]
pub(crate) mod realm; pub(crate) mod realm;
pub (crate) mod network; pub (crate) mod network;
pub(crate) mod create; pub(crate) mod create;

View File

@ -111,24 +111,23 @@ impl BridgeAllocator {
} }
fn new(bridge: &str, network: Ipv4Addr, mask_size: usize) -> BridgeAllocator { fn new(bridge: &str, network: Ipv4Addr, mask_size: usize) -> BridgeAllocator {
let allocator = BridgeAllocator { BridgeAllocator {
bridge: bridge.to_owned(), bridge: bridge.to_owned(),
allocated: HashSet::new(), allocated: HashSet::new(),
allocations: HashMap::new(), allocations: HashMap::new(),
network, mask_size, network, mask_size,
}; }
allocator
} }
pub fn allocate_address_for(&mut self, realm_name: &str) -> Result<String> { pub fn allocate_address_for(&mut self, realm_name: &str) -> Result<String> {
match self.find_free_address() { match self.find_free_address() {
Some(addr) => { Some(addr) => {
self.allocated.insert(addr.clone()); self.allocated.insert(addr);
if let Some(old) = self.allocations.insert(realm_name.to_owned(), addr.clone()) { if let Some(old) = self.allocations.insert(realm_name.to_owned(), addr) {
self.allocated.remove(&old); self.allocated.remove(&old);
} }
self.write_state()?; self.write_state()?;
return Ok(format!("{}/{}", addr, self.mask_size)); Ok(format!("{}/{}", addr, self.mask_size))
}, },
None => bail!("No free IP address could be found to assign to {}", realm_name), None => bail!("No free IP address could be found to assign to {}", realm_name),
} }
@ -136,7 +135,7 @@ impl BridgeAllocator {
} }
fn store_allocation(&mut self, realm_name: &str, address: Ipv4Addr) -> Result<()> { fn store_allocation(&mut self, realm_name: &str, address: Ipv4Addr) -> Result<()> {
self.allocated.insert(address.clone()); self.allocated.insert(address);
if let Some(old) = self.allocations.insert(realm_name.to_string(), address) { if let Some(old) = self.allocations.insert(realm_name.to_string(), address) {
self.allocated.remove(&old); self.allocated.remove(&old);
} }
@ -169,7 +168,7 @@ impl BridgeAllocator {
if octet < RESERVED_START { if octet < RESERVED_START {
bail!("Not a reserved octet: {}", octet); bail!("Not a reserved octet: {}", octet);
} }
let rsv = u32::from(self.network) | octet as u32; let rsv = u32::from(self.network) | u32::from(octet);
let addr = Ipv4Addr::from(rsv); let addr = Ipv4Addr::from(rsv);
let s = format!("{}/{}", addr, self.mask_size); let s = format!("{}/{}", addr, self.mask_size);
if self.allocated.contains(&addr) { if self.allocated.contains(&addr) {
@ -211,11 +210,11 @@ impl BridgeAllocator {
} }
fn parse_state_line(&mut self, line: &str) -> Result<()> { fn parse_state_line(&mut self, line: &str) -> Result<()> {
match line.find(":") { match line.find(':') {
Some(idx) => { Some(idx) => {
let (name,addr) = line.split_at(idx); let (name,addr) = line.split_at(idx);
let ip = addr[1..].parse::<Ipv4Addr>()?; let ip = addr[1..].parse::<Ipv4Addr>()?;
self.allocated.insert(ip.clone()); self.allocated.insert(ip);
self.allocations.insert(name.to_owned(), ip); self.allocations.insert(name.to_owned(), ip);
}, },
None => bail!("Could not parse line from network state file: {}", line), None => bail!("Could not parse line from network state file: {}", line),

View File

@ -26,7 +26,7 @@ enum RealmActiveState {
} }
impl RealmActiveState { impl RealmActiveState {
fn from_sysctl_output(line: &str) -> RealmActiveState { fn from_sysctl_output(line: &str) -> Self {
match line { match line {
"active" => RealmActiveState::Active, "active" => RealmActiveState::Active,
"inactive" => RealmActiveState::Inactive, "inactive" => RealmActiveState::Inactive,
@ -247,7 +247,7 @@ impl Realm {
pub fn cleanup_rootfs(&self) { pub fn cleanup_rootfs(&self) {
RealmOverlay::remove_any_overlay(self); RealmOverlay::remove_any_overlay(self);
if let Some(mountpoint) = self.realmfs_mountpoint() { if let Some(ref mountpoint) = self.realmfs_mountpoint() {
self.manager().release_mountpoint(mountpoint); self.manager().release_mountpoint(mountpoint);
} }

View File

@ -21,8 +21,8 @@ impl RealmMapList {
RealmMapList { manager, map, list } RealmMapList { manager, map, list }
} }
fn set_manager(&mut self, manager: Arc<RealmManager>) { fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager); self.manager = Arc::downgrade(manager);
self.list.iter_mut().for_each(|r| r.set_manager(manager.clone())); self.list.iter_mut().for_each(|r| r.set_manager(manager.clone()));
self.map.iter_mut().for_each(|(_,r)| r.set_manager(manager.clone())); self.map.iter_mut().for_each(|(_,r)| r.set_manager(manager.clone()));
} }
@ -55,6 +55,11 @@ impl RealmMapList {
} }
} }
pub enum HasCurrentChanged {
Changed(Option<Realm>),
NotChanged,
}
pub struct Realms { pub struct Realms {
manager: Weak<RealmManager>, manager: Weak<RealmManager>,
realms: RealmMapList, realms: RealmMapList,
@ -84,7 +89,8 @@ impl Realms {
fn all_realms(mark_active: bool) -> Result<Vec<Realm>> { fn all_realms(mark_active: bool) -> Result<Vec<Realm>> {
let mut v = Vec::new(); let mut v = Vec::new();
for entry in fs::read_dir(Realms::BASE_PATH)? { for entry in fs::read_dir(Realms::BASE_PATH)? {
if let Some(realm) = Realms::entry_to_realm(entry?) { let entry = entry?;
if let Some(realm) = Realms::entry_to_realm(&entry) {
v.push(realm); v.push(realm);
} }
} }
@ -94,14 +100,14 @@ impl Realms {
Ok(v) Ok(v)
} }
pub fn set_manager(&mut self, manager: Arc<RealmManager>) { pub fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager); self.manager = Arc::downgrade(manager);
self.realms.set_manager(manager); self.realms.set_manager(manager);
} }
// Examine a directory entry and if it looks like a legit realm directory // Examine a directory entry and if it looks like a legit realm directory
// extract realm name and return a `Realm` instance. // extract realm name and return a `Realm` instance.
fn entry_to_realm(entry: fs::DirEntry) -> Option<Realm> { fn entry_to_realm(entry: &fs::DirEntry) -> Option<Realm> {
match entry.path().symlink_metadata() { match entry.path().symlink_metadata() {
Ok(ref meta) if meta.is_dir() => {}, Ok(ref meta) if meta.is_dir() => {},
_ => return None, _ => return None,
@ -215,7 +221,7 @@ impl Realms {
// or when adding or removing a realm directory. // or when adding or removing a realm directory.
// //
fn realmslock() -> Result<FileLock> { fn realmslock() -> Result<FileLock> {
let lockpath = Path::new(Realms::BASE_PATH) let lockpath = Path::new(Self::BASE_PATH)
.join(".realmslock"); .join(".realmslock");
FileLock::acquire(lockpath) FileLock::acquire(lockpath)
@ -263,21 +269,20 @@ impl Realms {
} }
pub fn set_realm_current(&mut self, realm: &Realm) -> Result<()> { pub fn set_realm_current(&mut self, realm: &Realm) -> Result<()> {
symlink::write(realm.run_path(), Realms::current_realm_symlink(), true)?; symlink::write(realm.run_path(), Self::current_realm_symlink(), true)?;
self.last_current = Some(realm.clone()); self.last_current = Some(realm.clone());
Ok(()) Ok(())
} }
pub fn set_realm_default(&self, realm: &Realm) -> Result<()> { pub fn set_realm_default(&self, realm: &Realm) -> Result<()> {
symlink::write(realm.base_path(), Realms::default_symlink(), false) symlink::write(realm.base_path(), Self::default_symlink(), false)
} }
fn set_arbitrary_default(&mut self) -> Result<()> { fn set_arbitrary_default(&mut self) -> Result<()> {
// Prefer a recently used realm and don't choose a system realm // Prefer a recently used realm and don't choose a system realm
let choice = self.sorted() let choice = self.sorted()
.into_iter() .into_iter()
.filter(|r| !r.is_system()) .find(|r| !r.is_system());
.next();
if let Some(realm) = choice { if let Some(realm) = choice {
info!("Setting '{}' as new default realm", realm.name()); info!("Setting '{}' as new default realm", realm.name());
@ -305,25 +310,23 @@ impl Realms {
} }
pub fn current(&mut self) -> Option<Realm> { pub fn current(&mut self) -> Option<Realm> {
let current = Realms::current_realm_name().and_then(|name| self.by_name(&name)); let current = Self::current_realm_name().and_then(|name| self.by_name(&name));
self.last_current = current.clone(); self.last_current = current.clone();
current current
} }
// None : no it's the same pub fn has_current_changed(&mut self) -> HasCurrentChanged {
// Some() : yes and here's the new value
pub fn has_current_changed(&mut self) -> Option<Option<Realm>> {
let old = self.last_current.clone(); let old = self.last_current.clone();
let current = self.current(); let current = self.current();
if current == old { if current == old {
None HasCurrentChanged::NotChanged
} else { } else {
Some(current) HasCurrentChanged::Changed(current)
} }
} }
pub fn default(&self) -> Option<Realm> { pub fn default(&self) -> Option<Realm> {
Realms::default_realm_name().and_then(|name| self.by_name(&name)) Self::default_realm_name().and_then(|name| self.by_name(&name))
} }
/// Return the `Realm` marked as current, or `None` if no realm is current. /// Return the `Realm` marked as current, or `None` if no realm is current.
@ -338,7 +341,7 @@ impl Realms {
/// If the symlink exists it will point to run path of the current realm. /// If the symlink exists it will point to run path of the current realm.
/// ///
pub fn load_current_realm() -> Option<Realm> { pub fn load_current_realm() -> Option<Realm> {
Realms::current_realm_name().map(|ref name| Realm::new(name)) Self::current_realm_name().map(|ref name| Realm::new(name))
} }
/// Return `true` if some realm has been marked as current. /// Return `true` if some realm has been marked as current.
@ -349,57 +352,57 @@ impl Realms {
/// /run/citadel/realms/current/current.realm /// /run/citadel/realms/current/current.realm
/// ///
pub fn is_some_realm_current() -> bool { pub fn is_some_realm_current() -> bool {
Realms::current_realm_symlink().exists() Self::current_realm_symlink().exists()
} }
/// Set no realm as current by removing the current.realm symlink. /// Set no realm as current by removing the current.realm symlink.
fn clear_current_realm() -> Result<()> { fn clear_current_realm() -> Result<()> {
symlink::remove(Realms::current_realm_symlink()) symlink::remove(Self::current_realm_symlink())
} }
/// Set no realm as default by removing the default.realm symlink. /// Set no realm as default by removing the default.realm symlink.
pub fn clear_default_realm() -> Result<()> { pub fn clear_default_realm() -> Result<()> {
symlink::remove(Realms::default_symlink()) symlink::remove(Self::default_symlink())
} }
// Path of 'current.realm' symlink // Path of 'current.realm' symlink
pub fn current_realm_symlink() -> PathBuf { pub fn current_realm_symlink() -> PathBuf {
Path::new(Realms::RUN_PATH) Path::new(Self::RUN_PATH)
.join("current") .join("current")
.join("current.realm") .join("current.realm")
} }
pub fn current_realm_name() -> Option<String> { pub fn current_realm_name() -> Option<String> {
Realms::read_current_realm_symlink().as_ref().and_then(Realms::path_to_realm_name) Self::read_current_realm_symlink().as_ref().and_then(Self::path_to_realm_name)
} }
pub fn read_current_realm_symlink() -> Option<PathBuf> { pub fn read_current_realm_symlink() -> Option<PathBuf> {
symlink::read(Realms::current_realm_symlink()) symlink::read(Self::current_realm_symlink())
} }
// Path of 'default.realm' symlink // Path of 'default.realm' symlink
pub fn default_symlink() -> PathBuf { pub fn default_symlink() -> PathBuf {
Path::new(Realms::BASE_PATH) Path::new(Self::BASE_PATH)
.join("default.realm") .join("default.realm")
} }
pub fn default_realm_name() -> Option<String> { pub fn default_realm_name() -> Option<String> {
Realms::read_default_symlink().as_ref().and_then(Realms::path_to_realm_name) Self::read_default_symlink().as_ref().and_then(Self::path_to_realm_name)
} }
fn read_default_symlink() -> Option<PathBuf> { fn read_default_symlink() -> Option<PathBuf> {
symlink::read(Realms::default_symlink()) symlink::read(Self::default_symlink())
} }
fn path_to_realm_name(path: impl AsRef<Path>) -> Option<String> { fn path_to_realm_name(path: impl AsRef<Path>) -> Option<String> {
let path = path.as_ref(); let path = path.as_ref();
if path.starts_with(Realms::BASE_PATH) { if path.starts_with(Self::BASE_PATH) {
path.strip_prefix(Realms::BASE_PATH).ok() path.strip_prefix(Self::BASE_PATH).ok()
} else if path.starts_with(Realms::RUN_PATH) { } else if path.starts_with(Self::RUN_PATH) {
path.strip_prefix(Realms::RUN_PATH).ok() path.strip_prefix(Self::RUN_PATH).ok()
} else { } else {
None None
}.and_then(Realms::dir_to_realm_name) }.and_then(Self::dir_to_realm_name)
} }
fn dir_to_realm_name(dir: &Path) -> Option<String> { fn dir_to_realm_name(dir: &Path) -> Option<String> {

View File

@ -6,10 +6,10 @@ use crate::realmfs::mountpoint::Mountpoint;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::verity::Verity; use crate::verity::Verity;
/// Holds the activation status for a RealmFS and provides a thread-safe /// Holds the activation status for a `RealmFS` and provides a thread-safe
/// interface to it. /// interface to it.
/// ///
/// If `state` is `None` then the RealmFS is not currently activated. /// If `state` is `None` then the `RealmFS` is not currently activated.
/// ///
pub struct ActivationState { pub struct ActivationState {
state: RwLock<Option<Arc<Activation>>>, state: RwLock<Option<Arc<Activation>>>,
@ -33,7 +33,7 @@ impl ActivationState {
let activator = LoopActivator::new(realmfs); let activator = LoopActivator::new(realmfs);
activator.activation() activator.activation()
}; };
*self.state_mut() = activation.map(|a| Arc::new(a)) *self.state_mut() = activation.map(Arc::new)
} }
/// If currently activated return the corresponding `Activation` instance /// If currently activated return the corresponding `Activation` instance
@ -103,10 +103,10 @@ impl ActivationState {
} }
} }
/// Represents a RealmFS in an activated state. The activation can be one of: /// Represents a `RealmFS` in an activated state. The activation can be one of:
/// ///
/// `Activation::Loop` if the RealmFS is unsealed /// `Activation::Loop` if the `RealmFS` is unsealed
/// `Activation::Verity` if the RealmFS is sealed /// `Activation::Verity` if the `RealmFS` is sealed
/// ///
#[derive(Debug)] #[derive(Debug)]
pub enum Activation { pub enum Activation {
@ -149,12 +149,12 @@ impl Activation {
if mountpoint.tag() == "rw" || mountpoint.tag() == "ro" { if mountpoint.tag() == "rw" || mountpoint.tag() == "ro" {
LoopDevice::find_mounted_loop(mountpoint.path()).map(|loopdev| { LoopDevice::find_mounted_loop(mountpoint.path()).map(|loopdev| {
let (ro,rw) = Mountpoint::new_loop_pair(mountpoint.realmfs()); let (ro,rw) = Mountpoint::new_loop_pair(mountpoint.realmfs());
Activation::new_loop(ro, rw, loopdev) Self::new_loop(ro, rw, loopdev)
}) })
} else { } else {
let device = Verity::device_name_for_mountpoint(mountpoint); let device = Verity::device_name_for_mountpoint(mountpoint);
if Path::new("/dev/mapper").join(&device).exists() { if Path::new("/dev/mapper").join(&device).exists() {
Some(Activation::new_verity(mountpoint.clone(), device)) Some(Self::new_verity(mountpoint.clone(), device))
} else { } else {
None None
} }

View File

@ -3,6 +3,7 @@ mod activator;
mod mountpoint; mod mountpoint;
mod update; mod update;
pub(crate) mod realmfs_set; pub(crate) mod realmfs_set;
#[allow(clippy::module_inception)]
mod realmfs; mod realmfs;
pub use self::realmfs::RealmFS; pub use self::realmfs::RealmFS;

View File

@ -79,7 +79,7 @@ impl Mountpoint {
fn field(&self, n: usize) -> &str { fn field(&self, n: usize) -> &str {
Self::filename_fields(self.path()) Self::filename_fields(self.path())
.and_then(|mut fields| fields.nth(n)) .and_then(|mut fields| fields.nth(n))
.expect(&format!("Failed to access field {} of mountpoint {}", n, self)) .unwrap_or_else(|| panic!("Failed to access field {} of mountpoint {}", n, self))
} }
/// Return `true` if this instance is a `&Path` in `RealmFS::RUN_DIRECTORY` and /// Return `true` if this instance is a `&Path` in `RealmFS::RUN_DIRECTORY` and
@ -90,11 +90,11 @@ impl Mountpoint {
} }
fn has_valid_extention(&self) -> bool { fn has_valid_extention(&self) -> bool {
self.path().extension().map(|e| e == "mountpoint").unwrap_or(false) self.path().extension().map_or(false, |e| e == "mountpoint")
} }
fn filename_fields(path: &Path) -> Option<impl Iterator<Item=&str>> { fn filename_fields(path: &Path) -> Option<impl Iterator<Item=&str>> {
Self::filename(path).map(|name| name.split("-")) Self::filename(path).map(|name| name.split('-'))
} }
fn filename(path: &Path) -> Option<&str> { fn filename(path: &Path) -> Option<&str> {

View File

@ -68,24 +68,24 @@ impl RealmFS {
pub const USER_KEYNAME: &'static str = "realmfs-user"; pub const USER_KEYNAME: &'static str = "realmfs-user";
/// Locate a RealmFS image by name in the default location using the standard name convention /// Locate a RealmFS image by name in the default location using the standard name convention
pub fn load_by_name(name: &str) -> Result<RealmFS> { pub fn load_by_name(name: &str) -> Result<Self> {
RealmFS::validate_name(name)?; Self::validate_name(name)?;
let path = RealmFS::image_path(name); let path = Self::image_path(name);
if !path.exists() { if !path.exists() {
bail!("No image found at {}", path.display()); bail!("No image found at {}", path.display());
} }
RealmFS::load_from_path(path) Self::load_from_path(path)
} }
/// Load RealmFS image from an exact path. /// Load RealmFS image from an exact path.
pub fn load_from_path(path: impl AsRef<Path>) -> Result<RealmFS> { pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self> {
Self::_load_from_path(path.as_ref(), true) Self::_load_from_path(path.as_ref(), true)
} }
fn _load_from_path(path: &Path, load_activation: bool) -> Result<RealmFS> { fn _load_from_path(path: &Path, load_activation: bool) -> Result<Self> {
let path = Arc::new(path.to_owned()); let path = Arc::new(path.to_owned());
let header = RealmFS::load_realmfs_header(&path)?; let header = Self::load_realmfs_header(&path)?;
let name = header.metainfo().realmfs_name() let name = header.metainfo().realmfs_name()
.expect("RealmFS does not have a name") .expect("RealmFS does not have a name")
.to_owned(); .to_owned();
@ -130,7 +130,7 @@ impl RealmFS {
} }
pub fn is_valid_realmfs_image(path: impl AsRef<Path>) -> bool { pub fn is_valid_realmfs_image(path: impl AsRef<Path>) -> bool {
RealmFS::load_realmfs_header(path.as_ref()).is_ok() Self::load_realmfs_header(path.as_ref()).is_ok()
} }
fn load_realmfs_header(path: &Path) -> Result<ImageHeader> { fn load_realmfs_header(path: &Path) -> Result<ImageHeader> {
@ -143,7 +143,7 @@ impl RealmFS {
bail!("Image file {} is not a realmfs image", path.display()); bail!("Image file {} is not a realmfs image", path.display());
} }
match metainfo.realmfs_name() { match metainfo.realmfs_name() {
Some(name) => RealmFS::validate_name(name)?, Some(name) => Self::validate_name(name)?,
None => bail!("RealmFS image file {} does not have a 'realmfs-name' field", path.display()), None => bail!("RealmFS image file {} does not have a 'realmfs-name' field", path.display()),
}; };
Ok(header) Ok(header)
@ -151,7 +151,7 @@ impl RealmFS {
/// Return an Error result if name is not valid. /// Return an Error result if name is not valid.
fn validate_name(name: &str) -> Result<()> { fn validate_name(name: &str) -> Result<()> {
if RealmFS::is_valid_name(name) { if Self::is_valid_name(name) {
Ok(()) Ok(())
} else { } else {
Err(format_err!("Invalid realm name '{}'", name)) Err(format_err!("Invalid realm name '{}'", name))
@ -173,11 +173,11 @@ impl RealmFS {
if !util::is_valid_name(name, MAX_REALMFS_NAME_LEN) { if !util::is_valid_name(name, MAX_REALMFS_NAME_LEN) {
return false; return false;
} }
RealmFS::is_valid_realmfs_image(RealmFS::image_path(name)) Self::is_valid_realmfs_image(Self::image_path(name))
} }
fn image_path(name: &str) -> PathBuf { fn image_path(name: &str) -> PathBuf {
Path::new(RealmFS::BASE_PATH).join(format!("{}-realmfs.img", name)) Path::new(Self::BASE_PATH).join(format!("{}-realmfs.img", name))
} }
/// Return the `Path` to this RealmFS image file. /// Return the `Path` to this RealmFS image file.
@ -284,14 +284,14 @@ impl RealmFS {
self.activation_state.deactivate(&active) self.activation_state.deactivate(&active)
} }
pub fn fork(&self, new_name: &str) -> Result<RealmFS> { pub fn fork(&self, new_name: &str) -> Result<Self> {
self._fork(new_name, true) self._fork(new_name, true)
} }
/// Create an unsealed copy of this RealmFS image with a new image name. /// Create an unsealed copy of this RealmFS image with a new image name.
/// ///
pub fn fork_unsealed(&self, new_name: &str) -> Result<RealmFS> { pub fn fork_unsealed(&self, new_name: &str) -> Result<Self> {
RealmFS::validate_name(new_name)?; Self::validate_name(new_name)?;
info!("forking RealmFS image '{}' to new name '{}'", self.name(), new_name); info!("forking RealmFS image '{}' to new name '{}'", self.name(), new_name);
let new_path = self.path_with_filename(format!("{}-realmfs.img", new_name)); let new_path = self.path_with_filename(format!("{}-realmfs.img", new_name));
@ -305,8 +305,8 @@ impl RealmFS {
Ok(new_realmfs) Ok(new_realmfs)
} }
fn _fork(&self, new_name: &str, sealed_fork: bool) -> Result<RealmFS> { fn _fork(&self, new_name: &str, sealed_fork: bool) -> Result<Self> {
RealmFS::validate_name(new_name)?; Self::validate_name(new_name)?;
info!("forking RealmFS image '{}' to new name '{}'", self.name(), new_name); info!("forking RealmFS image '{}' to new name '{}'", self.name(), new_name);
let new_path = self.path_with_filename(format!("{}-realmfs.img", new_name)); let new_path = self.path_with_filename(format!("{}-realmfs.img", new_name));
if new_path.exists() { if new_path.exists() {
@ -328,18 +328,18 @@ impl RealmFS {
self.path().extension() == Some(OsStr::new("update")) self.path().extension() == Some(OsStr::new("update"))
} }
pub(crate) fn update_copy(&self) -> Result<RealmFS> { pub(crate) fn update_copy(&self) -> Result<Self> {
let path = self.path_with_extension("update"); let path = self.path_with_extension("update");
let name = self.name().to_string() + "-update"; let name = self.name().to_string() + "-update";
self.copy_image(&path, &name, false) self.copy_image(&path, &name, false)
} }
fn copy_image(&self, path: &Path, name: &str, sealed_copy: bool) -> Result<RealmFS> { fn copy_image(&self, path: &Path, name: &str, sealed_copy: bool) -> Result<Self> {
if path.exists() { if path.exists() {
bail!("Cannot create sealed copy because target path '{}' already exists", path.display()); bail!("Cannot create sealed copy because target path '{}' already exists", path.display());
} }
cmd!("/usr/bin/cp", "--reflink=auto {} {}", self.path.display(), path.display())?; cmd!("/usr/bin/cp", "--reflink=auto {} {}", self.path.display(), path.display())?;
let mut realmfs = RealmFS::_load_from_path(path, false)?; let mut realmfs = Self::_load_from_path(path, false)?;
self.with_manager(|m| realmfs.set_manager(m)); self.with_manager(|m| realmfs.set_manager(m));
realmfs.name = Arc::new(name.to_owned()); realmfs.name = Arc::new(name.to_owned());
@ -365,13 +365,13 @@ impl RealmFS {
let metainfo = self.metainfo(); let metainfo = self.metainfo();
let metainfo_bytes = self.generate_sealed_metainfo(self.name(), metainfo.verity_salt(), metainfo.verity_root()); let metainfo_bytes = self.generate_sealed_metainfo(self.name(), metainfo.verity_salt(), metainfo.verity_root());
let sig = keys.sign(&metainfo_bytes); let sig = keys.sign(&metainfo_bytes);
self.write_new_metainfo(metainfo_bytes, Some(sig)) self.write_new_metainfo(&metainfo_bytes, Some(sig))
} }
/// Convert to unsealed RealmFS image by removing dm-verity metadata and hash tree /// Convert to unsealed RealmFS image by removing dm-verity metadata and hash tree
pub fn unseal(&self) -> Result<()> { pub fn unseal(&self) -> Result<()> {
let bytes = RealmFS::generate_unsealed_metainfo(self.name(), self.metainfo().nblocks(), None); let bytes = Self::generate_unsealed_metainfo(self.name(), self.metainfo().nblocks(), None);
self.write_new_metainfo(bytes, None)?; self.write_new_metainfo(&bytes, None)?;
if self.has_verity_tree() { if self.has_verity_tree() {
self.truncate_verity()?; self.truncate_verity()?;
} }
@ -384,7 +384,7 @@ impl RealmFS {
} }
if let Some(activation) = self.activation() { if let Some(activation) = self.activation() {
let rw_mountpoint = activation.mountpoint_rw() let rw_mountpoint = activation.mountpoint_rw()
.ok_or(format_err!("unsealed activation expected"))?; .ok_or_else(|| format_err!("unsealed activation expected"))?;
if self.manager().active_mountpoints().contains(rw_mountpoint) { if self.manager().active_mountpoints().contains(rw_mountpoint) {
bail!("Cannot set owner realm because RW mountpoint is in use (by current owner?)"); bail!("Cannot set owner realm because RW mountpoint is in use (by current owner?)");
} }
@ -397,12 +397,12 @@ impl RealmFS {
if self.is_sealed() { if self.is_sealed() {
bail!("Cannot update metainfo on sealed realmfs image"); bail!("Cannot update metainfo on sealed realmfs image");
} }
let metainfo_bytes = RealmFS::generate_unsealed_metainfo(name, nblocks, owner_realm); let metainfo_bytes = Self::generate_unsealed_metainfo(name, nblocks, owner_realm);
self.write_new_metainfo(metainfo_bytes, None) self.write_new_metainfo(&metainfo_bytes, None)
} }
fn write_new_metainfo(&self, bytes: Vec<u8>, sig: Option<Signature>) -> Result<()> { fn write_new_metainfo(&self, bytes: &[u8], sig: Option<Signature>) -> Result<()> {
self.header.set_metainfo_bytes(&bytes)?; self.header.set_metainfo_bytes(bytes)?;
if let Some(sig) = sig { if let Some(sig) = sig {
self.header.set_signature(sig.to_bytes())?; self.header.set_signature(sig.to_bytes())?;
} }
@ -421,7 +421,7 @@ impl RealmFS {
} }
fn generate_sealed_metainfo(&self, name: &str, verity_salt: &str, verity_root: &str) -> Vec<u8> { fn generate_sealed_metainfo(&self, name: &str, verity_salt: &str, verity_root: &str) -> Vec<u8> {
let mut v = RealmFS::generate_unsealed_metainfo(name, self.metainfo().nblocks(), None); let mut v = Self::generate_unsealed_metainfo(name, self.metainfo().nblocks(), None);
writeln!(v, "channel = \"{}\"", Self::USER_KEYNAME).unwrap(); writeln!(v, "channel = \"{}\"", Self::USER_KEYNAME).unwrap();
writeln!(v, "verity-salt = \"{}\"", verity_salt).unwrap(); writeln!(v, "verity-salt = \"{}\"", verity_salt).unwrap();
writeln!(v, "verity-root = \"{}\"", verity_root).unwrap(); writeln!(v, "verity-root = \"{}\"", verity_root).unwrap();
@ -499,7 +499,7 @@ impl RealmFS {
let name = new_name.unwrap_or_else(|| self.name()); let name = new_name.unwrap_or_else(|| self.name());
let mut realmfs = RealmFS::load_from_path(&tmp)?; let mut realmfs = Self::load_from_path(&tmp)?;
realmfs.set_manager(self.manager()); realmfs.set_manager(self.manager());
let finish = || { let finish = || {
@ -525,7 +525,7 @@ impl RealmFS {
let salt = hex::encode(randombytes(32)); let salt = hex::encode(randombytes(32));
let output = Verity::new(self.path()).generate_image_hashtree_with_salt(&self.metainfo(), &salt)?; let output = Verity::new(self.path()).generate_image_hashtree_with_salt(&self.metainfo(), &salt)?;
let root_hash = output.root_hash() let root_hash = output.root_hash()
.ok_or(format_err!("no root hash returned from verity format operation"))?; .ok_or_else(|| format_err!("no root hash returned from verity format operation"))?;
info!("root hash is {}", output.root_hash().unwrap()); info!("root hash is {}", output.root_hash().unwrap());
info!("Signing new image with user realmfs keys"); info!("Signing new image with user realmfs keys");
@ -533,7 +533,7 @@ impl RealmFS {
let sig = keys.sign(&metainfo_bytes); let sig = keys.sign(&metainfo_bytes);
self.header().set_flag(ImageHeader::FLAG_HASH_TREE); self.header().set_flag(ImageHeader::FLAG_HASH_TREE);
self.write_new_metainfo(metainfo_bytes, Some(sig)) self.write_new_metainfo(&metainfo_bytes, Some(sig))
} }
pub fn has_sealing_keys(&self) -> bool { pub fn has_sealing_keys(&self) -> bool {
@ -545,7 +545,7 @@ impl RealmFS {
} }
pub fn rotate(&self, new_file: &Path) -> Result<()> { pub fn rotate(&self, new_file: &Path) -> Result<()> {
let backup = |n: usize| Path::new(RealmFS::BASE_PATH).join(format!("{}-realmfs.img.{}", self.name(), n)); let backup = |n: usize| Path::new(Self::BASE_PATH).join(format!("{}-realmfs.img.{}", self.name(), n));
for i in (1..NUM_BACKUPS).rev() { for i in (1..NUM_BACKUPS).rev() {
let from = backup(i - 1); let from = backup(i - 1);
@ -590,8 +590,7 @@ impl RealmFS {
/// this `RealmFS` /// this `RealmFS`
pub fn release_mountpoint(&self, mountpoint: &Mountpoint) -> bool { pub fn release_mountpoint(&self, mountpoint: &Mountpoint) -> bool {
let is_ours = self.activation() let is_ours = self.activation()
.map(|a| a.is_mountpoint(mountpoint)) .map_or(false, |a| a.is_mountpoint(mountpoint));
.unwrap_or(false);
if is_ours { if is_ours {
if let Err(e) = self.deactivate() { if let Err(e) = self.deactivate() {

View File

@ -21,14 +21,15 @@ impl RealmFSSet {
fn load_all() -> Result<Vec<RealmFS>> { fn load_all() -> Result<Vec<RealmFS>> {
let mut v = Vec::new(); let mut v = Vec::new();
for entry in fs::read_dir(RealmFS::BASE_PATH)? { for entry in fs::read_dir(RealmFS::BASE_PATH)? {
if let Some(realmfs) = Self::entry_to_realmfs(entry?) { let entry = entry?;
if let Some(realmfs) = Self::entry_to_realmfs(&entry) {
v.push(realmfs) v.push(realmfs)
} }
} }
Ok(v) Ok(v)
} }
fn entry_to_realmfs(entry: fs::DirEntry) -> Option<RealmFS> { fn entry_to_realmfs(entry: &fs::DirEntry) -> Option<RealmFS> {
if let Ok(filename) = entry.file_name().into_string() { if let Ok(filename) = entry.file_name().into_string() {
if filename.ends_with("-realmfs.img") { if filename.ends_with("-realmfs.img") {
let name = filename.trim_end_matches("-realmfs.img"); let name = filename.trim_end_matches("-realmfs.img");
@ -40,7 +41,7 @@ impl RealmFSSet {
None None
} }
pub fn set_manager(&mut self, manager: Arc<RealmManager>) { pub fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.realmfs_map.iter_mut().for_each(|(_,v)| v.set_manager(manager.clone())) self.realmfs_map.iter_mut().for_each(|(_,v)| v.set_manager(manager.clone()))
} }

View File

@ -13,7 +13,7 @@ const BLOCKS_PER_GIG: usize = 1024 * BLOCKS_PER_MEG;
const RESIZE2FS: &str = "resize2fs"; const RESIZE2FS: &str = "resize2fs";
// If less than 1gb remaining space // If less than 1gb remaining space
const AUTO_RESIZE_MINIMUM_FREE: ResizeSize = ResizeSize(1 * BLOCKS_PER_GIG); const AUTO_RESIZE_MINIMUM_FREE: ResizeSize = ResizeSize(BLOCKS_PER_GIG);
// ... add 4gb to size of image // ... add 4gb to size of image
const AUTO_RESIZE_INCREASE_SIZE: ResizeSize = ResizeSize(4 * BLOCKS_PER_GIG); const AUTO_RESIZE_INCREASE_SIZE: ResizeSize = ResizeSize(4 * BLOCKS_PER_GIG);
@ -21,19 +21,20 @@ pub struct ImageResizer<'a> {
image: &'a RealmFS, image: &'a RealmFS,
} }
#[derive(Copy,Clone)]
pub struct ResizeSize(usize); pub struct ResizeSize(usize);
impl ResizeSize { impl ResizeSize {
pub fn gigs(n: usize) -> ResizeSize { pub fn gigs(n: usize) -> Self {
ResizeSize(BLOCKS_PER_GIG * n) ResizeSize(BLOCKS_PER_GIG * n)
} }
pub fn megs(n: usize) -> ResizeSize { pub fn megs(n: usize) -> Self {
ResizeSize(BLOCKS_PER_MEG * n) ResizeSize(BLOCKS_PER_MEG * n)
} }
pub fn blocks(n: usize) -> ResizeSize { pub fn blocks(n: usize) -> Self {
ResizeSize(n) ResizeSize(n)
} }
@ -150,13 +151,14 @@ impl <'a> ImageResizer<'a> {
const SUPERBLOCK_SIZE: usize = 1024; const SUPERBLOCK_SIZE: usize = 1024;
pub struct Superblock([u8; SUPERBLOCK_SIZE]); pub struct Superblock([u8; SUPERBLOCK_SIZE]);
impl Superblock { impl Superblock {
fn new() -> Superblock { fn new() -> Self {
Superblock([0u8; SUPERBLOCK_SIZE]) Superblock([0u8; SUPERBLOCK_SIZE])
} }
pub fn load(path: impl AsRef<Path>, offset: u64) -> Result<Superblock> { pub fn load(path: impl AsRef<Path>, offset: u64) -> Result<Self> {
let mut sb = Superblock::new(); let mut sb = Self::new();
let mut file = File::open(path.as_ref())?; let mut file = File::open(path.as_ref())?;
file.seek(SeekFrom::Start(1024 + offset))?; file.seek(SeekFrom::Start(1024 + offset))?;
file.read_exact(&mut sb.0)?; file.read_exact(&mut sb.0)?;
@ -172,8 +174,8 @@ impl Superblock {
} }
fn split_u64(&self, offset_lo: usize, offset_hi: usize) -> u64 { fn split_u64(&self, offset_lo: usize, offset_hi: usize) -> u64 {
let lo = self.u32(offset_lo) as u64; let lo = u64::from(self.u32(offset_lo));
let hi = self.u32(offset_hi) as u64; let hi = u64::from(self.u32(offset_hi));
(hi << 32) | lo (hi << 32) | lo
} }

View File

@ -63,7 +63,7 @@ impl <'a> Update<'a> {
.map_err(|e| format_err!("failed to activate update image: {}", e))?; .map_err(|e| format_err!("failed to activate update image: {}", e))?;
activation.mountpoint_rw().cloned() activation.mountpoint_rw().cloned()
.ok_or(format_err!("Update image activation does not have a writeable mountpoint")) .ok_or_else(|| format_err!("Update image activation does not have a writeable mountpoint"))
} }
pub fn run_update_shell(&mut self, command: &str) -> Result<()> { pub fn run_update_shell(&mut self, command: &str) -> Result<()> {
@ -83,7 +83,7 @@ impl <'a> Update<'a> {
.arg("--quiet") .arg("--quiet")
.arg(format!("--machine={}", self.name())) .arg(format!("--machine={}", self.name()))
.arg(format!("--directory={}", mountpoint)) .arg(format!("--directory={}", mountpoint))
.arg(format!("--network-zone=clear")) .arg("--network-zone=clear")
.arg("/bin/bash") .arg("/bin/bash")
.arg("-c") .arg("-c")
.arg(command) .arg(command)

View File

@ -39,8 +39,8 @@ impl ResourceImage {
/// Locate and return a resource image of type `image_type`. /// Locate and return a resource image of type `image_type`.
/// First the /run/citadel/images directory is searched, and if not found there, /// First the /run/citadel/images directory is searched, and if not found there,
/// the image will be searched for in /storage/resources/$channel /// the image will be searched for in /storage/resources/$channel
pub fn find(image_type: &str) -> Result<ResourceImage> { pub fn find(image_type: &str) -> Result<Self> {
let channel = ResourceImage::rootfs_channel(); let channel = Self::rootfs_channel();
info!("Searching run directory for image {} with channel {}", image_type, channel); info!("Searching run directory for image {} with channel {}", image_type, channel);
@ -48,7 +48,7 @@ impl ResourceImage {
return Ok(image); return Ok(image);
} }
if !ResourceImage::ensure_storage_mounted()? { if !Self::ensure_storage_mounted()? {
bail!("Unable to mount /storage"); bail!("Unable to mount /storage");
} }
@ -62,24 +62,24 @@ impl ResourceImage {
} }
pub fn mount_image_type(image_type: &str) -> Result<()> { pub fn mount_image_type(image_type: &str) -> Result<()> {
let mut image = ResourceImage::find(image_type)?; let mut image = Self::find(image_type)?;
image.mount() image.mount()
} }
/// Locate a rootfs image in /run/citadel/images and return it /// Locate a rootfs image in /run/citadel/images and return it
pub fn find_rootfs() -> Result<ResourceImage> { pub fn find_rootfs() -> Result<Self> {
match search_directory(RUN_DIRECTORY, "rootfs", None)? { match search_directory(RUN_DIRECTORY, "rootfs", None)? {
Some(image) => Ok(image), Some(image) => Ok(image),
None => Err(format_err!("Failed to find rootfs resource image")), None => Err(format_err!("Failed to find rootfs resource image")),
} }
} }
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<ResourceImage> { pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self> {
let header = ImageHeader::from_file(path.as_ref())?; let header = ImageHeader::from_file(path.as_ref())?;
if !header.is_magic_valid() { if !header.is_magic_valid() {
bail!("Image file {} does not have a valid header", path.as_ref().display()); bail!("Image file {} does not have a valid header", path.as_ref().display());
} }
Ok(ResourceImage::new(path.as_ref(), header )) Ok(Self::new(path.as_ref(), header ))
} }
pub fn is_valid_image(&self) -> bool { pub fn is_valid_image(&self) -> bool {
@ -103,7 +103,7 @@ impl ResourceImage {
self.header.metainfo() self.header.metainfo()
} }
fn new(path: &Path, header: ImageHeader) -> ResourceImage { fn new(path: &Path, header: ImageHeader) -> Self {
assert_eq!(path.extension(), Some(OsStr::new("img")), "image filename must have .img extension"); assert_eq!(path.extension(), Some(OsStr::new("img")), "image filename must have .img extension");
ResourceImage { ResourceImage {
@ -297,14 +297,14 @@ impl ResourceImage {
// If no colon character is present then the source and target paths are the same. // If no colon character is present then the source and target paths are the same.
// The source path from the mounted resource image will be bind mounted to the target path on the system rootfs. // The source path from the mounted resource image will be bind mounted to the target path on the system rootfs.
fn process_manifest_line(&self, line: &str) -> Result<()> { fn process_manifest_line(&self, line: &str) -> Result<()> {
let line = line.trim_left_matches('/'); let line = line.trim_start_matches('/');
let (path_from, path_to) = if line.contains(":") { let (path_from, path_to) = if line.contains(':') {
let v = line.split(":").collect::<Vec<_>>(); let v = line.split(':').collect::<Vec<_>>();
if v.len() != 2 { if v.len() != 2 {
bail!("badly formed line '{}'", line); bail!("badly formed line '{}'", line);
} }
(v[0], v[1].trim_left_matches('/')) (v[0], v[1].trim_start_matches('/'))
} else { } else {
(line, line) (line, line)
}; };
@ -418,7 +418,7 @@ fn parse_timestamp(img: &ResourceImage) -> Result<usize> {
fn current_kernel_version() -> String { fn current_kernel_version() -> String {
let utsname = UtsName::uname(); let utsname = UtsName::uname();
let v = utsname.release().split("-").collect::<Vec<_>>(); let v = utsname.release().split('-').collect::<Vec<_>>();
v[0].to_string() v[0].to_string()
} }
@ -484,10 +484,8 @@ fn maybe_add_dir_entry(entry: DirEntry,
return Ok(()) return Ok(())
} }
if image_type == "kernel" { if image_type == "kernel" && (metainfo.kernel_version() != kernel_version || metainfo.kernel_id() != kernel_id) {
if metainfo.kernel_version() != kernel_version || metainfo.kernel_id() != kernel_id { return Ok(());
return Ok(());
}
} }
images.push(ResourceImage::new(&path, header)); images.push(ResourceImage::new(&path, header));

View File

@ -7,7 +7,7 @@ use crate::Result;
pub fn read(path: impl AsRef<Path>) -> Option<PathBuf> { pub fn read(path: impl AsRef<Path>) -> Option<PathBuf> {
let path = path.as_ref(); let path = path.as_ref();
if !fs::symlink_metadata(path).is_ok() { if fs::symlink_metadata(path).is_err() {
return None; return None;
} }
@ -44,8 +44,8 @@ pub fn write(target: impl AsRef<Path>, link: impl AsRef<Path>, tmp_in_parent: bo
} }
fn write_tmp_path(link: &Path, tmp_in_parent: bool) -> PathBuf { fn write_tmp_path(link: &Path, tmp_in_parent: bool) -> PathBuf {
let skip = if tmp_in_parent { 2 } else { 1 }; let n = if tmp_in_parent { 2 } else { 1 };
let tmp_dir = link.ancestors().skip(skip).next() let tmp_dir = link.ancestors().nth(n)
.expect("No parent directory in write_symlink"); .expect("No parent directory in write_symlink");
let mut tmp_fname = link.file_name() let mut tmp_fname = link.file_name()

View File

@ -24,7 +24,7 @@ impl LoopDevice {
args += &format!("--offset {} ", offset); args += &format!("--offset {} ", offset);
} }
if read_only { if read_only {
args += &format!("--read-only "); args += "--read-only ";
} }
args += &format!("-f --show {}", image.display()); args += &format!("-f --show {}", image.display());
let output = cmd_with_output!(Self::LOSETUP, args)?; let output = cmd_with_output!(Self::LOSETUP, args)?;
@ -64,8 +64,8 @@ impl LoopDevice {
// /dev/loop1: [0036]:64845938 (/storage/resources/dev/citadel-extra-dev-001.img), offset 4096 // /dev/loop1: [0036]:64845938 (/storage/resources/dev/citadel-extra-dev-001.img), offset 4096
let output:String = cmd_with_output!(Self::LOSETUP, "-j {}", image.display())?; let output:String = cmd_with_output!(Self::LOSETUP, "-j {}", image.display())?;
Ok(output.lines() Ok(output.lines()
.flat_map(|line| line.splitn(2, ":").next()) .flat_map(|line| line.splitn(2, ':').next())
.map(|s| LoopDevice::new(s)) .map(LoopDevice::new)
.collect()) .collect())
} }

View File

@ -3,6 +3,7 @@ use crate::Result;
use crate::terminal::{RawTerminal, Color, Base16Scheme}; use crate::terminal::{RawTerminal, Color, Base16Scheme};
use std::io::{self,Read,Write,Stdout}; use std::io::{self,Read,Write,Stdout};
#[derive(Default)]
pub struct AnsiControl(String); pub struct AnsiControl(String);
impl AnsiControl { impl AnsiControl {
@ -11,50 +12,45 @@ impl AnsiControl {
const OSC: char = ']'; const OSC: char = ']';
const ST: char = '\\'; const ST: char = '\\';
pub fn new() -> Self {
AnsiControl(String::new())
}
pub fn osc(n: u32) -> Self { pub fn osc(n: u32) -> Self {
AnsiControl::new() Self::default()
.push(AnsiControl::ESC) .push(Self::ESC)
.push(AnsiControl::OSC) .push(Self::OSC)
.num(n) .num(n)
} }
pub fn csi() -> Self { pub fn csi() -> Self {
AnsiControl::new() Self::default()
.push(AnsiControl::ESC) .push(Self::ESC)
.push(AnsiControl::CSI) .push(Self::CSI)
} }
pub fn bold() -> Self { pub fn bold() -> Self {
AnsiControl::csi().push_str("1m") Self::csi().push_str("1m")
} }
pub fn unbold() -> Self { pub fn unbold() -> Self {
AnsiControl::csi().push_str("22m") Self::csi().push_str("22m")
} }
pub fn clear() -> Self { pub fn clear() -> Self {
AnsiControl::csi().push_str("2J") Self::csi().push_str("2J")
} }
pub fn goto(x: u16, y: u16) -> Self { pub fn goto(x: u16, y: u16) -> Self {
AnsiControl::csi().push_str(x.to_string()).push(';').push_str(y.to_string()).push('H') Self::csi().push_str(x.to_string()).push(';').push_str(y.to_string()).push('H')
} }
pub fn set_window_title<S: AsRef<str>>(title: S) -> AnsiControl { pub fn set_window_title<S: AsRef<str>>(title: S) -> Self {
// AnsiControl::osc(2).sep().push_str(title.as_ref()).st() Self::osc(0).sep().push_str(title.as_ref()).st()
AnsiControl::osc(0).sep().push_str(title.as_ref()).st()
} }
pub fn window_title_push_stack() -> AnsiControl { pub fn window_title_push_stack() -> Self {
AnsiControl::csi().push_str("22;2t") Self::csi().push_str("22;2t")
} }
pub fn window_title_pop_stack() -> AnsiControl { pub fn window_title_pop_stack() -> Self {
AnsiControl::csi().push_str("23;2t") Self::csi().push_str("23;2t")
} }
pub fn sep(self) -> Self { pub fn sep(self) -> Self {
@ -70,7 +66,7 @@ impl AnsiControl {
} }
pub fn st(self) -> Self { pub fn st(self) -> Self {
self.push(AnsiControl::ESC).push(AnsiControl::ST) self.push(Self::ESC).push(Self::ST)
} }
pub fn push_str<S: AsRef<str>>(mut self, s: S) -> Self { pub fn push_str<S: AsRef<str>>(mut self, s: S) -> Self {
@ -92,8 +88,8 @@ impl AnsiControl {
} }
fn parse_color_response(s: &str) -> Result<Vec<(u32, Color)>> { fn parse_color_response(s: &str) -> Result<Vec<(u32, Color)>> {
let prefix = AnsiControl::osc(4).sep(); let prefix = Self::osc(4).sep();
let suffix = AnsiControl::new().st(); let suffix = Self::default().st();
let mut res = Vec::new(); let mut res = Vec::new();
let mut ptr = s; let mut ptr = s;
@ -104,14 +100,14 @@ impl AnsiControl {
None => bail!(":("), None => bail!(":("),
}; };
let (elem, s) = s.split_at(offset); let (elem, s) = s.split_at(offset);
res.push(AnsiControl::parse_idx_color_pair(elem)?); res.push(Self::parse_idx_color_pair(elem)?);
ptr = s.trim_start_matches(suffix.as_str()); ptr = s.trim_start_matches(suffix.as_str());
} }
Ok(res) Ok(res)
} }
fn parse_idx_color_pair(s: &str) -> Result<(u32, Color)> { fn parse_idx_color_pair(s: &str) -> Result<(u32, Color)> {
let v = s.split(";").collect::<Vec<_>>(); let v = s.split(';').collect::<Vec<_>>();
if v.len() != 2 { if v.len() != 2 {
bail!("bad elem {}", s); bail!("bad elem {}", s);
} }
@ -175,7 +171,7 @@ impl AnsiTerminal {
pub fn read_palette_bg(&mut self) -> Result<Color> { pub fn read_palette_bg(&mut self) -> Result<Color> {
let prefix = AnsiControl::osc(11).sep(); let prefix = AnsiControl::osc(11).sep();
let suffix = AnsiControl::new().st(); let suffix = AnsiControl::default().st();
self.write_code(AnsiControl::osc(11).sep().push('?').st())?; self.write_code(AnsiControl::osc(11).sep().push('?').st())?;
let response = self.read_response()?; let response = self.read_response()?;
let color = Color::parse(response.trim_start_matches(prefix.as_str()).trim_end_matches(suffix.as_str()))?; let color = Color::parse(response.trim_start_matches(prefix.as_str()).trim_end_matches(suffix.as_str()))?;
@ -184,7 +180,7 @@ impl AnsiTerminal {
} }
pub fn read_palette_fg(&mut self) -> Result<Color> { pub fn read_palette_fg(&mut self) -> Result<Color> {
let prefix = AnsiControl::osc(10).sep(); let prefix = AnsiControl::osc(10).sep();
let suffix = AnsiControl::new().st(); let suffix = AnsiControl::default().st();
self.write_code(AnsiControl::osc(10).sep().push('?').st())?; self.write_code(AnsiControl::osc(10).sep().push('?').st())?;
let response = self.read_response()?; let response = self.read_response()?;
let color = Color::parse(response.trim_start_matches(prefix.as_str()).trim_end_matches(suffix.as_str()))?; let color = Color::parse(response.trim_start_matches(prefix.as_str()).trim_end_matches(suffix.as_str()))?;

View File

@ -1,4 +1,4 @@
#![allow(clippy::unreadable_literal)]
use std::collections::HashMap; use std::collections::HashMap;
use crate::terminal::{Color, Base16Shell}; use crate::terminal::{Color, Base16Shell};
use crate::{Realm, Result, util, RealmManager}; use crate::{Realm, Result, util, RealmManager};
@ -24,7 +24,7 @@ impl Base16Scheme {
const BASE16_SHELL_FILE: &'static str = ".base16rc"; const BASE16_SHELL_FILE: &'static str = ".base16rc";
const BASE16_VIM_FILE: &'static str = ".base16vim"; const BASE16_VIM_FILE: &'static str = ".base16vim";
pub fn by_name(name: &str) -> Option<&'static Base16Scheme> { pub fn by_name(name: &str) -> Option<&'static Self> {
SCHEMES.get(name) SCHEMES.get(name)
} }
@ -34,8 +34,8 @@ impl Base16Scheme {
v v
} }
pub fn all_schemes() -> Vec<Base16Scheme> { pub fn all_schemes() -> Vec<Self> {
let mut v: Vec<Base16Scheme> = let mut v: Vec<Self> =
SCHEMES.values().cloned().collect(); SCHEMES.values().cloned().collect();
v.sort_by(|a,b| a.name().cmp(b.name())); v.sort_by(|a,b| a.name().cmp(b.name()));
@ -70,12 +70,12 @@ impl Base16Scheme {
None None
} }
pub fn new(slug: &str, name: &str, v: Vec<u32>) -> Base16Scheme { pub fn new(slug: &str, name: &str, v: Vec<u32>) -> Self {
assert_eq!(v.len(), 16); assert_eq!(v.len(), 16);
let mut colors = [Color::default();16]; let mut colors = [Color::default();16];
let cs = v.iter().map(|&c| Base16Scheme::u32_to_color(c)).collect::<Vec<_>>(); let cs = v.iter().map(|&c| Self::u32_to_color(c)).collect::<Vec<_>>();
colors.copy_from_slice(&cs); colors.copy_from_slice(&cs);
let category = Base16Scheme::find_category(name); let category = Self::find_category(name);
Base16Scheme { Base16Scheme {
name: name.to_string(), name: name.to_string(),
slug: slug.to_string(), slug: slug.to_string(),
@ -110,7 +110,7 @@ impl Base16Scheme {
} }
pub fn terminal_palette_color(&self, idx: usize) -> Color { pub fn terminal_palette_color(&self, idx: usize) -> Color {
self.color(Base16Scheme::TERM_MAP[idx]) self.color(Self::TERM_MAP[idx])
} }
pub fn apply_to_realm(&self, manager: &RealmManager, realm: &Realm) -> Result<()> { pub fn apply_to_realm(&self, manager: &RealmManager, realm: &Realm) -> Result<()> {
@ -925,7 +925,7 @@ fn create_schemes() -> HashMap<String, Base16Scheme> {
vec![ vec![
0x1B2B34, 0x343D46, 0x4F5B66, 0x65737E, 0x1B2B34, 0x343D46, 0x4F5B66, 0x65737E,
0xA7ADBA, 0xC0C5CE, 0xCDD3DE, 0xD8DEE9, 0xA7ADBA, 0xC0C5CE, 0xCDD3DE, 0xD8DEE9,
0xEC5f67, 0xF99157, 0xFAC863, 0x99C794, 0xEC5F67, 0xF99157, 0xFAC863, 0x99C794,
0x5FB3B3, 0x6699CC, 0xC594C5, 0xAB7967, 0x5FB3B3, 0x6699CC, 0xC594C5, 0xAB7967,
])); ]));
@ -1029,7 +1029,7 @@ fn create_schemes() -> HashMap<String, Base16Scheme> {
vec![ vec![
0x151718, 0x282a2b, 0x3B758C, 0x41535B, 0x151718, 0x282a2b, 0x3B758C, 0x41535B,
0x43a5d5, 0xd6d6d6, 0xeeeeee, 0xffffff, 0x43a5d5, 0xd6d6d6, 0xeeeeee, 0xffffff,
0xCd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56, 0xcd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56,
0x55dbbe, 0x55b5db, 0xa074c4, 0x8a553f, 0x55dbbe, 0x55b5db, 0xa074c4, 0x8a553f,
])); ]));

View File

@ -13,18 +13,18 @@ impl Color {
pub fn parse(s: &str) -> Result<Color> { pub fn parse(s: &str) -> Result<Color> {
if s.starts_with("rgb:") { if s.starts_with("rgb:") {
let v = s.trim_start_matches("rgb:").split("/").collect::<Vec<_>>(); let parts = s.trim_start_matches("rgb:").split('/').collect::<Vec<_>>();
if v.len() == 3 { if parts.len() == 3 {
let r = u16::from_str_radix(&v[0], 16)?; let r = u16::from_str_radix(&parts[0], 16)?;
let g = u16::from_str_radix(&v[1], 16)?; let g = u16::from_str_radix(&parts[1], 16)?;
let b = u16::from_str_radix(&v[2], 16)?; let b = u16::from_str_radix(&parts[2], 16)?;
return Ok(Color(r, g, b)) return Ok(Color(r, g, b))
} }
} }
Err(format_err!("Cannot parse '{}'", s)) Err(format_err!("Cannot parse '{}'", s))
} }
pub fn rgb(&self) -> (u16,u16,u16) { pub fn rgb(self) -> (u16,u16,u16) {
(self.0, self.1, self.2) (self.0, self.1, self.2)
} }
} }
@ -88,9 +88,7 @@ impl TerminalPalette {
self.fg = terminal.read_palette_fg()?; self.fg = terminal.read_palette_fg()?;
let idxs = (0..22).collect::<Vec<_>>(); let idxs = (0..22).collect::<Vec<_>>();
let colors = terminal.read_palette_colors(&idxs)?; let colors = terminal.read_palette_colors(&idxs)?;
for i in 0..self.palette.len() { self.palette.clone_from_slice(&colors);
self.palette[i] = colors[i];
}
Ok(()) Ok(())
} }

View File

@ -67,6 +67,7 @@ pub fn sha256<P: AsRef<Path>>(path: P) -> Result<String> {
Ok(v[0].trim().to_owned()) Ok(v[0].trim().to_owned())
} }
#[derive(Copy,Clone)]
pub enum FileRange { pub enum FileRange {
All, All,
Offset(usize), Offset(usize),
@ -78,13 +79,13 @@ fn ranged_reader<P: AsRef<Path>>(path: P, range: FileRange) -> Result<Box<dyn Re
let offset = match range { let offset = match range {
FileRange::All => 0, FileRange::All => 0,
FileRange::Offset(n) => n, FileRange::Offset(n) => n,
FileRange::Range {offset, len: _} => offset, FileRange::Range {offset, .. } => offset,
}; };
if offset > 0 { if offset > 0 {
f.seek(SeekFrom::Start(offset as u64))?; f.seek(SeekFrom::Start(offset as u64))?;
} }
let r = BufReader::new(f); let r = BufReader::new(f);
if let FileRange::Range {offset: _, len} = range { if let FileRange::Range {len, ..} = range {
Ok(Box::new(r.take(len as u64))) Ok(Box::new(r.take(len as u64)))
} else { } else {
Ok(Box::new(r)) Ok(Box::new(r))
@ -191,7 +192,7 @@ fn _copy_tree(from_base: &Path, to_base: &Path, chown_to: Option<(u32,u32)>) ->
for entry in WalkDir::new(from_base) { for entry in WalkDir::new(from_base) {
let path = entry?.path().to_owned(); let path = entry?.path().to_owned();
let to = to_base.join(path.strip_prefix(from_base)?); let to = to_base.join(path.strip_prefix(from_base)?);
if &to != to_base { if to != to_base {
copy_path(&path, &to, chown_to) copy_path(&path, &to, chown_to)
.map_err(|e| format_err!("failed to copy {} to {}: {}", path.display(), to.display(), e))?; .map_err(|e| format_err!("failed to copy {} to {}: {}", path.display(), to.display(), e))?;
} }

View File

@ -125,7 +125,7 @@ pub struct VerityOutput {
impl VerityOutput { impl VerityOutput {
/// Parse the string `output` as standard output from the dm-verity /// Parse the string `output` as standard output from the dm-verity
/// `veritysetup format` command. /// `veritysetup format` command.
fn parse(output: &str) -> VerityOutput { fn parse(output: &str) -> Self {
let mut vo = VerityOutput { let mut vo = VerityOutput {
output: output.to_owned(), output: output.to_owned(),
map: HashMap::new(), map: HashMap::new(),