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
**/*.rs.bk
**/*.iml

View File

@ -140,8 +140,8 @@ impl Backend {
}
fn apply_colors(&self, colors: theme::ColorPair) {
with_color(&colors.front, |c| self.write(tcolor::Fg(c)));
with_color(&colors.back, |c| self.write(tcolor::Bg(c)));
with_color(colors.front, |c| self.write(tcolor::Fg(c)));
with_color(colors.back, |c| self.write(tcolor::Bg(c)));
}
fn map_key(&mut self, event: TEvent) -> Event {
@ -257,7 +257,7 @@ impl backend::Backend for Backend {
self.current_style.set(color);
}
return current_style;
current_style
}
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
F: FnOnce(&dyn tcolor::Color) -> R,
{
match *clr {
match clr {
theme::Color::TerminalDefault => f(&tcolor::Reset),
theme::Color::Dark(theme::BaseColor::Black) => f(&tcolor::Black),
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.
if signals.wait().count() > 0 {
// XXX fixed to avoid panic
if resize_running.load(Ordering::Relaxed) {
if let Err(_) = resize_sender.send(()) {
return;
}
if resize_running.load(Ordering::Relaxed) && resize_sender.send(()).is_err() {
return;
}
}
}

View File

@ -232,7 +232,7 @@ impl FieldLayout {
};
let labels = labels
.into_iter()
.iter()
.map(pad_label)
.collect();
@ -308,7 +308,7 @@ pub trait DialogButtonAdapter: Finder+ViewWrapper {
{
let id = self.inner_id();
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 {
@ -322,9 +322,9 @@ pub trait DialogButtonAdapter: Finder+ViewWrapper {
fn set_button_enabled(&mut self, button: usize, enabled: bool) {
self.call_on_dialog(|d| {
d.buttons_mut()
.nth(button)
.map(|b| b.set_enabled(enabled));
if let Some(b) = d.buttons_mut().nth(button) {
b.set_enabled(enabled);
}
})
}
@ -416,8 +416,7 @@ impl ValidatorResult {
fn process(self, siv: &mut Cursive) {
match self {
ValidatorResult::Allow(cb) => (cb)(siv),
ValidatorResult::Deny(cb) => (cb)(siv),
ValidatorResult::Allow(cb) | ValidatorResult::Deny(cb) => (cb)(siv),
}
}
@ -470,7 +469,7 @@ impl TextValidator {
where F: FnOnce(&mut EditView) -> R {
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
{
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
@ -294,7 +293,7 @@ impl Inner {
}
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) {

View File

@ -79,10 +79,8 @@ impl RealmAction {
let msg = "Open terminal in realm '$REALM'?";
Self::confirm_action(title, msg, |r| {
let manager = r.manager();
if !r.is_active() {
if !Self::log_fail("starting realm", || manager.start_realm(r)) {
return;
}
if !r.is_active() && !Self::log_fail("starting realm", || manager.start_realm(r)) {
return;
}
Self::log_fail("starting terminal", || manager.launch_terminal(r));
})
@ -146,7 +144,7 @@ impl RealmAction {
EventResult::with_cb(|s| {
let realm = RealmAction::current_realm(s);
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| {
if let Err(e) = realm.save_notes(notes) {
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
{
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) {
@ -372,15 +372,13 @@ impl OptionEntry {
fn load(&mut self, config: &mut RealmConfig) {
let var = (self.accessor)(config);
self.value = var.clone();
self.original = var.clone();
self.value = *var;
self.original = *var;
self.default = self.resolve_default(config);
}
fn set(&mut self, v: bool) {
if v != self.default {
self.value = Some(v);
} else if Some(v) == self.original {
if v != self.default || self.original == Some(v) {
self.value = Some(v);
} else {
self.value = None;

View File

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

View File

@ -169,7 +169,7 @@ impl RealmFSAction {
EventResult::with_cb(|s| {
let realmfs = Self::current_realmfs(s);
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| {
if let Err(e) = realmfs.save_notes(notes) {
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
{
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 : ")
.dim_style()
.println(format!("{}", activation.device()))
.println(activation.device())
.pop();
let mount = if activation.mountpoint_rw().is_some() { "Mounts" } else { "Mount "};

View File

@ -46,7 +46,7 @@ impl ThemeHandler {
(0x3, "highlight_inactive"),
];
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
}
@ -55,13 +55,13 @@ impl ThemeHandler {
const DEFAULT_SCHEME: &'static str = "default-dark";
pub fn save_base16_theme(base16: &Base16Scheme) {
if let Err(e) = fs::write(ThemeHandler::SCHEME_CONF_PATH, base16.slug()) {
warn!("Error writing color scheme file ({}): {}", ThemeHandler::SCHEME_CONF_PATH, e);
if let Err(e) = fs::write(Self::SCHEME_CONF_PATH, base16.slug()) {
warn!("Error writing color scheme file ({}): {}", Self::SCHEME_CONF_PATH, e);
}
}
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() {
fs::read_to_string(path).ok().and_then(|ref s| Base16Scheme::by_name(s).cloned())
} else {
@ -70,8 +70,8 @@ impl ThemeHandler {
}
pub fn load_base16_theme() -> Theme {
let path = Path::new(ThemeHandler::SCHEME_CONF_PATH);
let mut scheme = Base16Scheme::by_name(ThemeHandler::DEFAULT_SCHEME).unwrap();
let path = Path::new(Self::SCHEME_CONF_PATH);
let mut scheme = Base16Scheme::by_name(Self::DEFAULT_SCHEME).unwrap();
if path.exists() {
if let Ok(scheme_name) = fs::read_to_string(path) {
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) {
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);
let theme = ThemeHandler::generate_base16_theme(v);
s.set_theme(theme);
@ -99,11 +99,11 @@ impl ThemeChooser {
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)
{
let select = ThemeChooser::create_tree_view(initial.clone(), cb);
let content = ThemeChooser::create_content(initial, select);
let select = Self::create_tree_view(initial.clone(), cb);
let content = Self::create_content(initial, select);
let inner = ViewBox::boxed(content);
ThemeChooser { inner }
}
@ -136,16 +136,16 @@ impl ThemeChooser {
where F: 'static + Fn(&mut Cursive, &Base16Scheme)
{
let mut tree = TreeView::new()
.on_select(ThemeChooser::on_tree_select)
.on_collapse(ThemeChooser::on_tree_collapse)
.on_select(Self::on_tree_select)
.on_collapse(Self::on_tree_collapse)
.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 {
(cb)(s, scheme);
}
});
ThemeChooser::populate_tree(initial, &mut tree);
Self::populate_tree(initial, &mut tree);
tree.with_id("theme-tree")
}
@ -154,7 +154,7 @@ impl ThemeChooser {
let mut category_rows = HashMap::new();
let mut last_row = 0;
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() {
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 is_initial {
tree.set_selected_row(new_row);
@ -198,7 +198,7 @@ impl ThemeChooser {
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 TreeItem::ColorScheme(scheme) = item {
@ -208,9 +208,9 @@ impl ThemeChooser {
}
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 &mut TreeItem::Category(ref _name, ref mut collapsed) = item {
if let TreeItem::Category(ref _name, ref mut collapsed) = *item {
*collapsed = is_collapsed;
}
}
@ -227,9 +227,9 @@ impl ThemeChooser {
fn toggle_expand_item(&self) -> EventResult {
EventResult::with_cb(|s| {
ThemeChooser::call_on_tree(s, |v| {
Self::call_on_tree(s, |v| {
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 {
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);
}
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 == "setup" => do_setup(),
Some(s) if s == "start-realms" => do_start_realms(),
@ -48,10 +47,8 @@ fn setup_keyring() -> Result<()> {
fn do_setup() -> Result<()> {
if CommandLine::live_mode() || CommandLine::install_mode() {
live::live_setup()?;
} else {
if let Err(err) = setup_keyring() {
warn!("Failed to setup keyring: {}", err);
}
} else if let Err(err) = setup_keyring() {
warn!("Failed to setup keyring: {}", err);
}
ResourceImage::mount_image_type("kernel")?;

View File

@ -89,7 +89,7 @@ fn choose_boot_partiton(scan: bool) -> Result<Partition> {
for p in partitions {
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> {

View File

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

View File

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

View File

@ -48,7 +48,7 @@ fn main() {
}
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() {
"boot" => boot::main(rebuild_args("citadel-boot", args)),
"install" => install::main(rebuild_args("citadel-install", args)),

View File

@ -8,7 +8,7 @@ mod build;
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,
None => {
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> {
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()
.skip(skip)
.take_while(|c| c.is_numeric())
@ -149,7 +149,7 @@ fn resize(arg_matches: &ArgMatches) -> Result<()> {
};
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)?;
if mode_add {

View File

@ -129,7 +129,7 @@ impl DesktopFile {
pub fn add_action_line(&mut self, action: &str, line: Line) {
if line.is_key_value_type() {
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);
}
self.lines.push(line);

View File

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

View File

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

View File

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

View File

@ -108,7 +108,7 @@ impl DesktopFileParser {
if let Line::KeyValue(ref k, ref value) = line {
if k == "Actions" {
for s in value.split_terminator(";") {
for s in value.split_terminator(';') {
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> {
s: &'a str,
@ -202,17 +202,17 @@ impl <'a> LineParser<'a> {
} else if content == "Desktop Entry" {
return Some(Line::DesktopHeader)
}
return Some(Line::GroupHeader(content.to_string()))
Some(Line::GroupHeader(content.to_string()))
}
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 {
return None
}
let key = parts[0].trim();
let val = parts[1].trim();
if !key.contains("[") {
if !key.contains('[') {
if key == "Exec" {
return Some(Line::ExecLine(val.to_string()))
}
@ -222,7 +222,7 @@ impl <'a> LineParser<'a> {
}
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 mut chars = loc.chars();
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.
pub fn noverity() -> bool {
CommandLine::var_exists("citadel.noverity")
Self::var_exists("citadel.noverity")
}
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.
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.
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.
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
pub fn sealed() -> bool { CommandLine::var_exists("citadel.sealed") }
pub fn sealed() -> bool { Self::var_exists("citadel.sealed") }
pub fn channel() -> Option<&'static str> {
CommandLine::get_value("citadel.channel")
Self::get_value("citadel.channel")
}
fn _channel() -> Option<(&'static str,Option<&'static str>)> {
if let Some(channel) = CommandLine::channel() {
let parts = channel.splitn(2, ":").collect::<Vec<_>>();
if let Some(channel) = Self::channel() {
let parts = channel.splitn(2, ':').collect::<Vec<_>>();
if parts.len() == 2 {
return Some((parts[0], Some(parts[1])))
}
@ -82,33 +82,33 @@ impl CommandLine {
}
pub fn channel_name() -> Option<&'static str> {
if let Some((name, _)) = CommandLine::_channel() {
if let Some((name, _)) = Self::_channel() {
return Some(name)
}
None
}
pub fn channel_pubkey() -> Option<&'static str> {
if let Some((_, pubkey)) = CommandLine::_channel() {
if let Some((_, pubkey)) = Self::_channel() {
return pubkey
}
None
}
pub fn verbose() -> bool {
CommandLine::var_exists("citadel.verbose")
Self::var_exists("citadel.verbose")
}
pub fn debug() -> bool {
CommandLine::var_exists("citadel.debug")
Self::var_exists("citadel.debug")
}
fn new() -> CommandLine {
fn new() -> Self {
CommandLine{ varmap: HashMap::new() }
}
fn load() -> Result<CommandLine> {
fn load() -> Result<Self> {
let s = fs::read_to_string("/proc/cmdline")?;
let varmap = CommandLineParser::new(s).parse();
Ok(CommandLine{varmap})
@ -157,7 +157,7 @@ struct CommandLineParser {
}
impl CommandLineParser {
fn new(cmdline: String) -> CommandLineParser {
fn new(cmdline: String) -> Self {
CommandLineParser {
cmdline,
varmap: HashMap::new(),

View File

@ -30,7 +30,7 @@ pub struct Exec {
}
impl Exec {
pub fn new(cmd: impl AsRef<str>) -> Exec {
pub fn new(cmd: impl AsRef<str>) -> Self {
Exec {
cmd_name: cmd.as_ref().to_string(),
cmd: Command::new(cmd.as_ref()),
@ -55,7 +55,7 @@ impl Exec {
for line in BufReader::new(result.stderr.as_slice()).lines() {
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.add_args(args.as_ref());
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())
}
@ -103,7 +103,7 @@ impl Exec {
self.cmd.args(args);
}
fn check_cmd_status(&self, status: &ExitStatus) -> Result<()> {
fn check_cmd_status(&self, status: ExitStatus) -> Result<()> {
if !status.success() {
match status.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<()> {
let path = Path::new(&self.cmd_name);
if !path.is_absolute() {
Exec::search_path(&self.cmd_name)?;
Self::search_path(&self.cmd_name)?;
return Ok(())
} else if path.exists() {
return Ok(())
@ -148,13 +148,13 @@ fn ranged_reader<P: AsRef<Path>>(path: P, range: FileRange) -> Result<Box<dyn Re
let offset = match range {
FileRange::All => 0,
FileRange::Offset(n) => n,
FileRange::Range {offset, len: _} => offset,
FileRange::Range {offset, ..} => offset,
};
if offset > 0 {
f.seek(SeekFrom::Start(offset as u64))?;
}
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)))
} else {
Ok(Box::new(r))

View File

@ -101,8 +101,8 @@ impl HeaderBytes {
}
fn read_u16(&self, idx: usize) -> u16 {
let hi = self.read_u8(idx) as u16;
let lo = self.read_u8(idx + 1) as u16;
let hi = u16::from(self.read_u8(idx));
let lo = u16::from(self.read_u8(idx + 1));
(hi << 8) | lo
}
@ -152,11 +152,8 @@ impl ImageHeader {
/// Size of header block
pub const HEADER_SIZE: usize = 4096;
pub fn new() -> ImageHeader {
let metainfo = Mutex::new(None);
let buffer = HeaderBytes::create_empty();
let timestamp = AtomicIsize::new(0);
ImageHeader { buffer, metainfo, timestamp }
pub fn new() -> Self {
Self::default()
}
/// Reload header if file has changed on disk
@ -184,14 +181,14 @@ impl ImageHeader {
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 (size,ts) = Self::file_metadata(path)?;
if size < Self::HEADER_SIZE {
bail!("Cannot load image header because {} has a size of {}", path.display(), size);
}
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;
Ok(header)
}
@ -202,14 +199,14 @@ impl ImageHeader {
Ok((metadata.len() as usize, metadata.mtime() as isize))
}
pub fn from_reader<R: Read>(r: &mut R) -> Result<ImageHeader> {
let mut v = vec![0u8; ImageHeader::HEADER_SIZE];
pub fn from_reader<R: Read>(r: &mut R) -> Result<Self> {
let mut v = vec![0u8; Self::HEADER_SIZE];
r.read_exact(&mut v)?;
Self::from_slice(&v)
}
fn from_slice(slice: &[u8]) -> Result<ImageHeader> {
assert_eq!(slice.len(), ImageHeader::HEADER_SIZE);
fn from_slice(slice: &[u8]) -> Result<Self> {
assert_eq!(slice.len(), Self::HEADER_SIZE);
let buffer = HeaderBytes::create_from_slice(slice);
let metainfo = Mutex::new(None);
let timestamp = AtomicIsize::new(0);
@ -218,7 +215,7 @@ impl ImageHeader {
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 nsectors = dev.nsectors()?;
ensure!(
@ -227,7 +224,7 @@ impl ImageHeader {
path.as_ref().display(),
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())?;
Self::from_slice(buffer.as_ref())
}
@ -276,7 +273,7 @@ impl ImageHeader {
let mut lock = self.metainfo.lock().unwrap();
let mb = self.metainfo_bytes();
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));
Ok(())
}
@ -338,7 +335,7 @@ impl ImageHeader {
pub fn set_metainfo_bytes(&self, bytes: &[u8]) -> Result<()> {
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();
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)]
pub struct MetaInfo {

View File

@ -29,14 +29,14 @@ pub struct KeyRing {
}
impl KeyRing {
pub fn create_new() -> KeyRing {
let seed = KeyRing::new_random_seed();
pub fn create_new() -> Self {
let seed = Self::new_random_seed();
let mut keypairs = HashMap::new();
keypairs.insert("realmfs-user".to_string(), hex::encode(&seed.0));
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());
sbox.read().map_err(|e| format_err!("Error reading keyring file: {}", e))?;
let mut bytes = sbox.open(passphrase)?;
@ -45,13 +45,13 @@ impl KeyRing {
Ok(keyring)
}
pub fn load_with_cryptsetup_passphrase<P: AsRef<Path>>(path: P) -> Result<KeyRing> {
let passphrase = KeyRing::get_cryptsetup_passphrase()?;
KeyRing::load(path, &passphrase)
pub fn load_with_cryptsetup_passphrase<P: AsRef<Path>>(path: P) -> Result<Self> {
let passphrase = Self::get_cryptsetup_passphrase()?;
Self::load(path, &passphrase)
}
fn get_cryptsetup_passphrase() -> Result<String> {
let key = KeyRing::get_key("cryptsetup")?;
let key = Self::get_key("cryptsetup")?;
info!("Got key {}", key.0);
let buf = key.read()?;
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);
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<()> {
@ -81,13 +81,13 @@ impl KeyRing {
info!("Adding {} to kernel keystore", k.as_str());
let bytes = hex::decode(v)?;
let key = KernelKey::add_key("user", k.as_str(), &bytes, KEY_SPEC_USER_KEYRING)?;
key.set_perm(0x3f030000)?;
key.set_perm(0x3f03_0000)?;
}
Ok(())
}
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()?;
KeyPair::from_bytes(&data)
}
@ -130,7 +130,7 @@ struct SecretBox {
}
impl SecretBox {
fn new(path: &Path) -> SecretBox {
fn new(path: &Path) -> Self {
SecretBox {
path: path.to_path_buf(),
salt: Salt([0; SALTBYTES]),
@ -151,7 +151,7 @@ impl SecretBox {
}
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)
.map_err(|_| format_err!("Failed to decrypt {}", self.path.display()))?;
Ok(result)
@ -180,31 +180,31 @@ pub struct KernelKey(int32_t);
impl KernelKey {
pub fn user_keyring() -> KernelKey {
pub fn user_keyring() -> Self {
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 description = CString::new(description).unwrap();
let serial = _request_key(key_type.as_ptr(), description.as_ptr())?;
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 description = CString::new(description).unwrap();
let serial = _add_key(key_type.as_ptr(), description.as_ptr(), payload.as_ptr(), payload.len(), ring_id)?;
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)?;
Ok(KernelKey(serial as i32))
}
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(())
}
@ -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 description = CString::new(description).unwrap();

View File

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

View File

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

View File

@ -24,7 +24,7 @@ pub enum OverlayType {
}
impl OverlayType {
pub fn from_str_value(value: &str) -> OverlayType {
pub fn from_str_value(value: &str) -> Self {
if value == "tmpfs" {
OverlayType::TmpFS
} 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 {
OverlayType::None => None,
OverlayType::TmpFS => Some("tmpfs"),
@ -122,25 +122,25 @@ pub struct RealmConfig {
impl RealmConfig {
/// 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)
.join(format!("realm-{}", realm_name))
.join("config");
let mut config = RealmConfig::empty();
let mut config = Self::empty();
config.path = path;
config
}
fn load_global_config() -> RealmConfig {
if let Some(mut global) = RealmConfig::load_config("/storage/realms/config") {
global.parent = Some(Box::new(RealmConfig::default()));
fn load_global_config() -> Self {
if let Some(mut global) = Self::load_config("/storage/realms/config") {
global.parent = Some(Box::new(Self::default()));
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() {
match fs::read_to_string(path.as_ref()) {
Ok(s) => return toml::from_str::<RealmConfig>(&s).ok(),
@ -177,7 +177,7 @@ impl RealmConfig {
let s = fs::read_to_string(&self.path)?;
*self = toml::from_str(&s)?;
} else {
*self = RealmConfig::empty();
*self = Self::empty();
}
self.path = path;
self.loaded = Some(self.read_mtime());
@ -185,7 +185,7 @@ impl RealmConfig {
Ok(())
}
pub fn default() -> RealmConfig {
pub fn default() -> Self {
RealmConfig {
use_shared_dir: Some(true),
use_ephemeral_home: Some(false),
@ -215,7 +215,7 @@ impl RealmConfig {
}
}
pub fn empty() -> RealmConfig {
pub fn empty() -> Self {
RealmConfig {
use_shared_dir: None,
use_ephemeral_home: None,
@ -394,8 +394,7 @@ impl RealmConfig {
/// The type of overlay on root filesystem to set up for this realm.
pub fn overlay(&self) -> OverlayType {
self.str_value(|c| c.overlay.as_ref())
.map(OverlayType::from_str_value)
.unwrap_or(OverlayType::None)
.map_or(OverlayType::None, OverlayType::from_str_value)
}
/// 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 crate::{RealmManager, Result, Realm};
use super::realms::HasCurrentChanged;
use dbus::{Connection, BusType, ConnectionItem, Message, Path};
use inotify::{Inotify, WatchMask, WatchDescriptor, Event};
@ -54,8 +55,8 @@ impl Inner {
}
}
fn set_manager(&mut self, manager: Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager);
fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(manager);
}
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);
}
@ -242,7 +243,7 @@ impl DbusEventListener {
fn handle_signal(&self, message: Message) -> Result<()> {
let member = message.member()
.ok_or(format_err!("invalid signal"))?;
.ok_or_else(|| format_err!("invalid signal"))?;
let (name, _path): (String, Path) = message.read2()?;
if let (Some(interface),Some(member)) = (message.interface(),message.member()) {
verbose!("DBUS: {}:[{}({})]", interface, member,name);
@ -343,7 +344,7 @@ impl InotifyEventListener {
fn handle_current_event(&self) {
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));
}
})

View File

@ -9,6 +9,7 @@ use crate::realmfs::realmfs_set::RealmFSSet;
use super::systemd::Systemd;
use super::network::NetworkConfig;
use super::events::{RealmEventListener, RealmEvent};
use crate::realm::realms::HasCurrentChanged;
pub struct RealmManager {
inner: RwLock<Inner>,
@ -38,25 +39,25 @@ impl RealmManager {
Ok(network)
}
pub fn load() -> Result<Arc<RealmManager>> {
pub fn load() -> Result<Arc<Self>> {
let inner = Inner::new()?;
let inner = RwLock::new(inner);
let network = RealmManager::create_network_config()?;
let network = Self::create_network_config()?;
let systemd = Systemd::new(network);
let manager = RealmManager{ inner, systemd };
let manager = Arc::new(manager);
manager.set_manager(manager.clone());
manager.set_manager(&manager);
Ok(manager)
}
fn set_manager(&self, manager: Arc<RealmManager>) {
fn set_manager(&self, manager: &Arc<RealmManager>) {
let mut inner = self.inner_mut();
inner.events.set_manager(manager.clone());
inner.realms.set_manager(manager.clone());
inner.events.set_manager(manager);
inner.realms.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<()> {
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() {
bail!("Current realm {} is not active?", realm.name());
@ -130,8 +131,7 @@ impl RealmManager {
.into_iter()
.filter(|r| {
r.realmfs_mountpoint()
.map(|mp| activation.is_mountpoint(&mp))
.unwrap_or(false)
.map_or(false, |mp| activation.is_mountpoint(&mp))
})
.collect()
}
@ -150,7 +150,7 @@ impl RealmManager {
/// Notify `RealmManager` that `mountpoint` has been released by a
/// `Realm`.
pub fn release_mountpoint(&self, mountpoint: Mountpoint) {
pub fn release_mountpoint(&self, mountpoint: &Mountpoint) {
info!("releasing mountpoint: {}", mountpoint);
if !mountpoint.is_valid() {
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 realmfs.release_mountpoint(&mountpoint) {
if realmfs.release_mountpoint(mountpoint) {
return;
}
}
if let Some(activation) = Activation::for_mountpoint(&mountpoint) {
if let Some(activation) = Activation::for_mountpoint(mountpoint) {
let active = self.active_mountpoints();
if let Err(e) = activation.deactivate(&active) {
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()
}

View File

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

View File

@ -111,24 +111,23 @@ impl BridgeAllocator {
}
fn new(bridge: &str, network: Ipv4Addr, mask_size: usize) -> BridgeAllocator {
let allocator = BridgeAllocator {
BridgeAllocator {
bridge: bridge.to_owned(),
allocated: HashSet::new(),
allocations: HashMap::new(),
network, mask_size,
};
allocator
}
}
pub fn allocate_address_for(&mut self, realm_name: &str) -> Result<String> {
match self.find_free_address() {
Some(addr) => {
self.allocated.insert(addr.clone());
if let Some(old) = self.allocations.insert(realm_name.to_owned(), addr.clone()) {
self.allocated.insert(addr);
if let Some(old) = self.allocations.insert(realm_name.to_owned(), addr) {
self.allocated.remove(&old);
}
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),
}
@ -136,7 +135,7 @@ impl BridgeAllocator {
}
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) {
self.allocated.remove(&old);
}
@ -169,7 +168,7 @@ impl BridgeAllocator {
if octet < RESERVED_START {
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 s = format!("{}/{}", addr, self.mask_size);
if self.allocated.contains(&addr) {
@ -211,11 +210,11 @@ impl BridgeAllocator {
}
fn parse_state_line(&mut self, line: &str) -> Result<()> {
match line.find(":") {
match line.find(':') {
Some(idx) => {
let (name,addr) = line.split_at(idx);
let ip = addr[1..].parse::<Ipv4Addr>()?;
self.allocated.insert(ip.clone());
self.allocated.insert(ip);
self.allocations.insert(name.to_owned(), ip);
},
None => bail!("Could not parse line from network state file: {}", line),

View File

@ -26,7 +26,7 @@ enum RealmActiveState {
}
impl RealmActiveState {
fn from_sysctl_output(line: &str) -> RealmActiveState {
fn from_sysctl_output(line: &str) -> Self {
match line {
"active" => RealmActiveState::Active,
"inactive" => RealmActiveState::Inactive,
@ -247,7 +247,7 @@ impl Realm {
pub fn cleanup_rootfs(&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);
}

View File

@ -21,8 +21,8 @@ impl RealmMapList {
RealmMapList { manager, map, list }
}
fn set_manager(&mut self, manager: Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager);
fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(manager);
self.list.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 {
manager: Weak<RealmManager>,
realms: RealmMapList,
@ -84,7 +89,8 @@ impl Realms {
fn all_realms(mark_active: bool) -> Result<Vec<Realm>> {
let mut v = Vec::new();
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);
}
}
@ -94,14 +100,14 @@ impl Realms {
Ok(v)
}
pub fn set_manager(&mut self, manager: Arc<RealmManager>) {
self.manager = Arc::downgrade(&manager);
pub fn set_manager(&mut self, manager: &Arc<RealmManager>) {
self.manager = Arc::downgrade(manager);
self.realms.set_manager(manager);
}
// Examine a directory entry and if it looks like a legit realm directory
// 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() {
Ok(ref meta) if meta.is_dir() => {},
_ => return None,
@ -215,7 +221,7 @@ impl Realms {
// or when adding or removing a realm directory.
//
fn realmslock() -> Result<FileLock> {
let lockpath = Path::new(Realms::BASE_PATH)
let lockpath = Path::new(Self::BASE_PATH)
.join(".realmslock");
FileLock::acquire(lockpath)
@ -263,21 +269,20 @@ impl Realms {
}
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());
Ok(())
}
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<()> {
// Prefer a recently used realm and don't choose a system realm
let choice = self.sorted()
.into_iter()
.filter(|r| !r.is_system())
.next();
.find(|r| !r.is_system());
if let Some(realm) = choice {
info!("Setting '{}' as new default realm", realm.name());
@ -305,25 +310,23 @@ impl Realms {
}
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();
current
}
// None : no it's the same
// Some() : yes and here's the new value
pub fn has_current_changed(&mut self) -> Option<Option<Realm>> {
pub fn has_current_changed(&mut self) -> HasCurrentChanged {
let old = self.last_current.clone();
let current = self.current();
if current == old {
None
HasCurrentChanged::NotChanged
} else {
Some(current)
HasCurrentChanged::Changed(current)
}
}
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.
@ -338,7 +341,7 @@ impl Realms {
/// If the symlink exists it will point to run path of the current 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.
@ -349,57 +352,57 @@ impl Realms {
/// /run/citadel/realms/current/current.realm
///
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.
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.
pub fn clear_default_realm() -> Result<()> {
symlink::remove(Realms::default_symlink())
symlink::remove(Self::default_symlink())
}
// Path of 'current.realm' symlink
pub fn current_realm_symlink() -> PathBuf {
Path::new(Realms::RUN_PATH)
Path::new(Self::RUN_PATH)
.join("current")
.join("current.realm")
}
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> {
symlink::read(Realms::current_realm_symlink())
symlink::read(Self::current_realm_symlink())
}
// Path of 'default.realm' symlink
pub fn default_symlink() -> PathBuf {
Path::new(Realms::BASE_PATH)
Path::new(Self::BASE_PATH)
.join("default.realm")
}
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> {
symlink::read(Realms::default_symlink())
symlink::read(Self::default_symlink())
}
fn path_to_realm_name(path: impl AsRef<Path>) -> Option<String> {
let path = path.as_ref();
if path.starts_with(Realms::BASE_PATH) {
path.strip_prefix(Realms::BASE_PATH).ok()
} else if path.starts_with(Realms::RUN_PATH) {
path.strip_prefix(Realms::RUN_PATH).ok()
if path.starts_with(Self::BASE_PATH) {
path.strip_prefix(Self::BASE_PATH).ok()
} else if path.starts_with(Self::RUN_PATH) {
path.strip_prefix(Self::RUN_PATH).ok()
} else {
None
}.and_then(Realms::dir_to_realm_name)
}.and_then(Self::dir_to_realm_name)
}
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 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.
///
/// 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 {
state: RwLock<Option<Arc<Activation>>>,
@ -33,7 +33,7 @@ impl ActivationState {
let activator = LoopActivator::new(realmfs);
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
@ -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::Verity` if the RealmFS is sealed
/// `Activation::Loop` if the `RealmFS` is unsealed
/// `Activation::Verity` if the `RealmFS` is sealed
///
#[derive(Debug)]
pub enum Activation {
@ -149,12 +149,12 @@ impl Activation {
if mountpoint.tag() == "rw" || mountpoint.tag() == "ro" {
LoopDevice::find_mounted_loop(mountpoint.path()).map(|loopdev| {
let (ro,rw) = Mountpoint::new_loop_pair(mountpoint.realmfs());
Activation::new_loop(ro, rw, loopdev)
Self::new_loop(ro, rw, loopdev)
})
} else {
let device = Verity::device_name_for_mountpoint(mountpoint);
if Path::new("/dev/mapper").join(&device).exists() {
Some(Activation::new_verity(mountpoint.clone(), device))
Some(Self::new_verity(mountpoint.clone(), device))
} else {
None
}

View File

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

View File

@ -79,7 +79,7 @@ impl Mountpoint {
fn field(&self, n: usize) -> &str {
Self::filename_fields(self.path())
.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
@ -90,11 +90,11 @@ impl Mountpoint {
}
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>> {
Self::filename(path).map(|name| name.split("-"))
Self::filename(path).map(|name| name.split('-'))
}
fn filename(path: &Path) -> Option<&str> {

View File

@ -68,24 +68,24 @@ impl RealmFS {
pub const USER_KEYNAME: &'static str = "realmfs-user";
/// Locate a RealmFS image by name in the default location using the standard name convention
pub fn load_by_name(name: &str) -> Result<RealmFS> {
RealmFS::validate_name(name)?;
let path = RealmFS::image_path(name);
pub fn load_by_name(name: &str) -> Result<Self> {
Self::validate_name(name)?;
let path = Self::image_path(name);
if !path.exists() {
bail!("No image found at {}", path.display());
}
RealmFS::load_from_path(path)
Self::load_from_path(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)
}
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 header = RealmFS::load_realmfs_header(&path)?;
let header = Self::load_realmfs_header(&path)?;
let name = header.metainfo().realmfs_name()
.expect("RealmFS does not have a name")
.to_owned();
@ -130,7 +130,7 @@ impl RealmFS {
}
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> {
@ -143,7 +143,7 @@ impl RealmFS {
bail!("Image file {} is not a realmfs image", path.display());
}
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()),
};
Ok(header)
@ -151,7 +151,7 @@ impl RealmFS {
/// Return an Error result if name is not valid.
fn validate_name(name: &str) -> Result<()> {
if RealmFS::is_valid_name(name) {
if Self::is_valid_name(name) {
Ok(())
} else {
Err(format_err!("Invalid realm name '{}'", name))
@ -173,11 +173,11 @@ impl RealmFS {
if !util::is_valid_name(name, MAX_REALMFS_NAME_LEN) {
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 {
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.
@ -284,14 +284,14 @@ impl RealmFS {
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)
}
/// Create an unsealed copy of this RealmFS image with a new image name.
///
pub fn fork_unsealed(&self, new_name: &str) -> Result<RealmFS> {
RealmFS::validate_name(new_name)?;
pub fn fork_unsealed(&self, new_name: &str) -> Result<Self> {
Self::validate_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));
@ -305,8 +305,8 @@ impl RealmFS {
Ok(new_realmfs)
}
fn _fork(&self, new_name: &str, sealed_fork: bool) -> Result<RealmFS> {
RealmFS::validate_name(new_name)?;
fn _fork(&self, new_name: &str, sealed_fork: bool) -> Result<Self> {
Self::validate_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));
if new_path.exists() {
@ -328,18 +328,18 @@ impl RealmFS {
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 name = self.name().to_string() + "-update";
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() {
bail!("Cannot create sealed copy because target path '{}' already exists", 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));
realmfs.name = Arc::new(name.to_owned());
@ -365,13 +365,13 @@ impl RealmFS {
let metainfo = self.metainfo();
let metainfo_bytes = self.generate_sealed_metainfo(self.name(), metainfo.verity_salt(), metainfo.verity_root());
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
pub fn unseal(&self) -> Result<()> {
let bytes = RealmFS::generate_unsealed_metainfo(self.name(), self.metainfo().nblocks(), None);
self.write_new_metainfo(bytes, None)?;
let bytes = Self::generate_unsealed_metainfo(self.name(), self.metainfo().nblocks(), None);
self.write_new_metainfo(&bytes, None)?;
if self.has_verity_tree() {
self.truncate_verity()?;
}
@ -384,7 +384,7 @@ impl RealmFS {
}
if let Some(activation) = self.activation() {
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) {
bail!("Cannot set owner realm because RW mountpoint is in use (by current owner?)");
}
@ -397,12 +397,12 @@ impl RealmFS {
if self.is_sealed() {
bail!("Cannot update metainfo on sealed realmfs image");
}
let metainfo_bytes = RealmFS::generate_unsealed_metainfo(name, nblocks, owner_realm);
self.write_new_metainfo(metainfo_bytes, None)
let metainfo_bytes = Self::generate_unsealed_metainfo(name, nblocks, owner_realm);
self.write_new_metainfo(&metainfo_bytes, None)
}
fn write_new_metainfo(&self, bytes: Vec<u8>, sig: Option<Signature>) -> Result<()> {
self.header.set_metainfo_bytes(&bytes)?;
fn write_new_metainfo(&self, bytes: &[u8], sig: Option<Signature>) -> Result<()> {
self.header.set_metainfo_bytes(bytes)?;
if let Some(sig) = sig {
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> {
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, "verity-salt = \"{}\"", verity_salt).unwrap();
writeln!(v, "verity-root = \"{}\"", verity_root).unwrap();
@ -499,7 +499,7 @@ impl RealmFS {
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());
let finish = || {
@ -525,7 +525,7 @@ impl RealmFS {
let salt = hex::encode(randombytes(32));
let output = Verity::new(self.path()).generate_image_hashtree_with_salt(&self.metainfo(), &salt)?;
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!("Signing new image with user realmfs keys");
@ -533,7 +533,7 @@ impl RealmFS {
let sig = keys.sign(&metainfo_bytes);
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 {
@ -545,7 +545,7 @@ impl RealmFS {
}
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() {
let from = backup(i - 1);
@ -590,8 +590,7 @@ impl RealmFS {
/// this `RealmFS`
pub fn release_mountpoint(&self, mountpoint: &Mountpoint) -> bool {
let is_ours = self.activation()
.map(|a| a.is_mountpoint(mountpoint))
.unwrap_or(false);
.map_or(false, |a| a.is_mountpoint(mountpoint));
if is_ours {
if let Err(e) = self.deactivate() {

View File

@ -21,14 +21,15 @@ impl RealmFSSet {
fn load_all() -> Result<Vec<RealmFS>> {
let mut v = Vec::new();
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)
}
}
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 filename.ends_with("-realmfs.img") {
let name = filename.trim_end_matches("-realmfs.img");
@ -40,7 +41,7 @@ impl RealmFSSet {
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()))
}

View File

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

View File

@ -63,7 +63,7 @@ impl <'a> Update<'a> {
.map_err(|e| format_err!("failed to activate update image: {}", e))?;
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<()> {
@ -83,7 +83,7 @@ impl <'a> Update<'a> {
.arg("--quiet")
.arg(format!("--machine={}", self.name()))
.arg(format!("--directory={}", mountpoint))
.arg(format!("--network-zone=clear"))
.arg("--network-zone=clear")
.arg("/bin/bash")
.arg("-c")
.arg(command)

View File

@ -39,8 +39,8 @@ impl ResourceImage {
/// Locate and return a resource image of type `image_type`.
/// First the /run/citadel/images directory is searched, and if not found there,
/// the image will be searched for in /storage/resources/$channel
pub fn find(image_type: &str) -> Result<ResourceImage> {
let channel = ResourceImage::rootfs_channel();
pub fn find(image_type: &str) -> Result<Self> {
let channel = Self::rootfs_channel();
info!("Searching run directory for image {} with channel {}", image_type, channel);
@ -48,7 +48,7 @@ impl ResourceImage {
return Ok(image);
}
if !ResourceImage::ensure_storage_mounted()? {
if !Self::ensure_storage_mounted()? {
bail!("Unable to mount /storage");
}
@ -62,24 +62,24 @@ impl ResourceImage {
}
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()
}
/// 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)? {
Some(image) => Ok(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())?;
if !header.is_magic_valid() {
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 {
@ -103,7 +103,7 @@ impl ResourceImage {
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");
ResourceImage {
@ -297,14 +297,14 @@ impl ResourceImage {
// 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.
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 v = line.split(":").collect::<Vec<_>>();
let (path_from, path_to) = if line.contains(':') {
let v = line.split(':').collect::<Vec<_>>();
if v.len() != 2 {
bail!("badly formed line '{}'", line);
}
(v[0], v[1].trim_left_matches('/'))
(v[0], v[1].trim_start_matches('/'))
} else {
(line, line)
};
@ -418,7 +418,7 @@ fn parse_timestamp(img: &ResourceImage) -> Result<usize> {
fn current_kernel_version() -> String {
let utsname = UtsName::uname();
let v = utsname.release().split("-").collect::<Vec<_>>();
let v = utsname.release().split('-').collect::<Vec<_>>();
v[0].to_string()
}
@ -484,10 +484,8 @@ fn maybe_add_dir_entry(entry: DirEntry,
return Ok(())
}
if image_type == "kernel" {
if metainfo.kernel_version() != kernel_version || metainfo.kernel_id() != kernel_id {
return Ok(());
}
if image_type == "kernel" && (metainfo.kernel_version() != kernel_version || metainfo.kernel_id() != kernel_id) {
return Ok(());
}
images.push(ResourceImage::new(&path, header));

View File

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

View File

@ -24,7 +24,7 @@ impl LoopDevice {
args += &format!("--offset {} ", offset);
}
if read_only {
args += &format!("--read-only ");
args += "--read-only ";
}
args += &format!("-f --show {}", image.display());
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
let output:String = cmd_with_output!(Self::LOSETUP, "-j {}", image.display())?;
Ok(output.lines()
.flat_map(|line| line.splitn(2, ":").next())
.map(|s| LoopDevice::new(s))
.flat_map(|line| line.splitn(2, ':').next())
.map(LoopDevice::new)
.collect())
}

View File

@ -3,6 +3,7 @@ use crate::Result;
use crate::terminal::{RawTerminal, Color, Base16Scheme};
use std::io::{self,Read,Write,Stdout};
#[derive(Default)]
pub struct AnsiControl(String);
impl AnsiControl {
@ -11,50 +12,45 @@ impl AnsiControl {
const OSC: char = ']';
const ST: char = '\\';
pub fn new() -> Self {
AnsiControl(String::new())
}
pub fn osc(n: u32) -> Self {
AnsiControl::new()
.push(AnsiControl::ESC)
.push(AnsiControl::OSC)
Self::default()
.push(Self::ESC)
.push(Self::OSC)
.num(n)
}
pub fn csi() -> Self {
AnsiControl::new()
.push(AnsiControl::ESC)
.push(AnsiControl::CSI)
Self::default()
.push(Self::ESC)
.push(Self::CSI)
}
pub fn bold() -> Self {
AnsiControl::csi().push_str("1m")
Self::csi().push_str("1m")
}
pub fn unbold() -> Self {
AnsiControl::csi().push_str("22m")
Self::csi().push_str("22m")
}
pub fn clear() -> Self {
AnsiControl::csi().push_str("2J")
Self::csi().push_str("2J")
}
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 {
// AnsiControl::osc(2).sep().push_str(title.as_ref()).st()
AnsiControl::osc(0).sep().push_str(title.as_ref()).st()
pub fn set_window_title<S: AsRef<str>>(title: S) -> Self {
Self::osc(0).sep().push_str(title.as_ref()).st()
}
pub fn window_title_push_stack() -> AnsiControl {
AnsiControl::csi().push_str("22;2t")
pub fn window_title_push_stack() -> Self {
Self::csi().push_str("22;2t")
}
pub fn window_title_pop_stack() -> AnsiControl {
AnsiControl::csi().push_str("23;2t")
pub fn window_title_pop_stack() -> Self {
Self::csi().push_str("23;2t")
}
pub fn sep(self) -> Self {
@ -70,7 +66,7 @@ impl AnsiControl {
}
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 {
@ -92,8 +88,8 @@ impl AnsiControl {
}
fn parse_color_response(s: &str) -> Result<Vec<(u32, Color)>> {
let prefix = AnsiControl::osc(4).sep();
let suffix = AnsiControl::new().st();
let prefix = Self::osc(4).sep();
let suffix = Self::default().st();
let mut res = Vec::new();
let mut ptr = s;
@ -104,14 +100,14 @@ impl AnsiControl {
None => bail!(":("),
};
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());
}
Ok(res)
}
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 {
bail!("bad elem {}", s);
}
@ -175,7 +171,7 @@ impl AnsiTerminal {
pub fn read_palette_bg(&mut self) -> Result<Color> {
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())?;
let response = self.read_response()?;
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> {
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())?;
let response = self.read_response()?;
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 crate::terminal::{Color, Base16Shell};
use crate::{Realm, Result, util, RealmManager};
@ -24,7 +24,7 @@ impl Base16Scheme {
const BASE16_SHELL_FILE: &'static str = ".base16rc";
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)
}
@ -34,8 +34,8 @@ impl Base16Scheme {
v
}
pub fn all_schemes() -> Vec<Base16Scheme> {
let mut v: Vec<Base16Scheme> =
pub fn all_schemes() -> Vec<Self> {
let mut v: Vec<Self> =
SCHEMES.values().cloned().collect();
v.sort_by(|a,b| a.name().cmp(b.name()));
@ -70,12 +70,12 @@ impl Base16Scheme {
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);
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);
let category = Base16Scheme::find_category(name);
let category = Self::find_category(name);
Base16Scheme {
name: name.to_string(),
slug: slug.to_string(),
@ -110,7 +110,7 @@ impl Base16Scheme {
}
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<()> {
@ -925,7 +925,7 @@ fn create_schemes() -> HashMap<String, Base16Scheme> {
vec![
0x1B2B34, 0x343D46, 0x4F5B66, 0x65737E,
0xA7ADBA, 0xC0C5CE, 0xCDD3DE, 0xD8DEE9,
0xEC5f67, 0xF99157, 0xFAC863, 0x99C794,
0xEC5F67, 0xF99157, 0xFAC863, 0x99C794,
0x5FB3B3, 0x6699CC, 0xC594C5, 0xAB7967,
]));
@ -1029,7 +1029,7 @@ fn create_schemes() -> HashMap<String, Base16Scheme> {
vec![
0x151718, 0x282a2b, 0x3B758C, 0x41535B,
0x43a5d5, 0xd6d6d6, 0xeeeeee, 0xffffff,
0xCd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56,
0xcd3f45, 0xdb7b55, 0xe6cd69, 0x9fca56,
0x55dbbe, 0x55b5db, 0xa074c4, 0x8a553f,
]));

View File

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

View File

@ -67,6 +67,7 @@ pub fn sha256<P: AsRef<Path>>(path: P) -> Result<String> {
Ok(v[0].trim().to_owned())
}
#[derive(Copy,Clone)]
pub enum FileRange {
All,
Offset(usize),
@ -78,13 +79,13 @@ fn ranged_reader<P: AsRef<Path>>(path: P, range: FileRange) -> Result<Box<dyn Re
let offset = match range {
FileRange::All => 0,
FileRange::Offset(n) => n,
FileRange::Range {offset, len: _} => offset,
FileRange::Range {offset, .. } => offset,
};
if offset > 0 {
f.seek(SeekFrom::Start(offset as u64))?;
}
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)))
} else {
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) {
let path = entry?.path().to_owned();
let to = to_base.join(path.strip_prefix(from_base)?);
if &to != to_base {
if to != to_base {
copy_path(&path, &to, chown_to)
.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 {
/// Parse the string `output` as standard output from the dm-verity
/// `veritysetup format` command.
fn parse(output: &str) -> VerityOutput {
fn parse(output: &str) -> Self {
let mut vo = VerityOutput {
output: output.to_owned(),
map: HashMap::new(),