ciruela 0.6.12

A peer-to-peer synchronization software for servers in datacenters.
Documentation
use std::io::{self, BufReader, BufRead};
use std::sync::Arc;

use ssh_keys::PublicKey;
use ssh_keys::openssh::parse_public_key;

use config::Directory;
use openat::Dir;
use metadata::{Error, Meta};


fn read_keys(dir: &Dir, name: &str, keys: &mut Vec<PublicKey>, absent_ok: bool)
{
    let f = match dir.open_file(name) {
        Ok(f) => f,
        Err(ref e) if e.kind() == io::ErrorKind::NotFound && absent_ok => {
            return;
        }
        Err(e) => {
            error!("Can't read key {:?}: {}", name, e);
            return;
        }
    };
    for line in BufReader::new(f).lines() {
        let line = match line {
            Ok(ref line) => line.trim(),
            Err(e) => {
                error!("Can't read key {:?}: {}", name, e);
                return;
            }
        };
        if line == "" || line.starts_with("#") {
            continue;
        }
        match parse_public_key(line) {
            Ok(key) => keys.push(key),
            Err(e) => {
                error!("Can't parse key {:?}: {}", name, e);
                return;
            }
        };
    }
}

pub fn read_upload_keys(cfg: &Arc<Directory>, meta: &Meta)
    -> Result<Vec<PublicKey>, Error>
{
    let mut res = Vec::new();
    let cfg_dir = Dir::open(&meta.0.config.config_dir)
        .map_err(|e| Error::ReadKey(meta.0.config.config_dir.clone(), e))?;
    read_keys(&cfg_dir, "master.key", &mut res, true);
    match cfg_dir.sub_dir("keys") {
        Ok(dir) => {
            for key in &cfg.upload_keys {
                read_keys(&dir, &format!("{}.key", key), &mut res, false);
            }
        }
        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
            for key in &cfg.upload_keys {
                error!("Can't read key {:?}: no such file", key);
            }
        }
        Err(e) => {
            return Err(Error::ReadKey(
                meta.0.config.config_dir.join("keys"), e));
        }
    }
    Ok(res)
}