<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![deny(nonminimal_bool, logic_bug)]

#[allow(unused, many_single_char_names)]
fn main() {
    let a: bool = unimplemented!();
    let b: bool = unimplemented!();
    let c: bool = unimplemented!();
    let d: bool = unimplemented!();
    let e: bool = unimplemented!();
    let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = a;
    let _ = !(a && b);
    let _ = !true; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = false;
    let _ = !false; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = true;
    let _ = !!a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = a;

    let _ = false && a; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;

    let _ = false || a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = a;

    // don't lint on cfgs
    let _ = cfg!(you_shall_not_not_pass) && a;

    let _ = a || !b || !c || !d || !e;

    let _ = !(a && b || c);

    let _ = !(!a && b); //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = !b || a;
}

#[allow(unused, many_single_char_names)]
fn equality_stuff() {
    let a: i32 = unimplemented!();
    let b: i32 = unimplemented!();
    let c: i32 = unimplemented!();
    let d: i32 = unimplemented!();
    let e: i32 = unimplemented!();
    let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = c == 5 && a == b;
    let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = c == 5 && a == b;
    let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a > b && a == b;
}
<commit_msg>more tests<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![deny(nonminimal_bool, logic_bug)]

#[allow(unused, many_single_char_names)]
fn main() {
    let a: bool = unimplemented!();
    let b: bool = unimplemented!();
    let c: bool = unimplemented!();
    let d: bool = unimplemented!();
    let e: bool = unimplemented!();
    let _ = a && b || a; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = a;
    let _ = !(a && b);
    let _ = !true; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = false;
    let _ = !false; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = true;
    let _ = !!a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = a;

    let _ = false && a; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;

    let _ = false || a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = a;

    // don't lint on cfgs
    let _ = cfg!(you_shall_not_not_pass) && a;

    let _ = a || !b || !c || !d || !e;

    let _ = !(a && b || c);

    let _ = !(!a && b); //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = !b || a;
}

#[allow(unused, many_single_char_names)]
fn equality_stuff() {
    let a: i32 = unimplemented!();
    let b: i32 = unimplemented!();
    let c: i32 = unimplemented!();
    let d: i32 = unimplemented!();
    let e: i32 = unimplemented!();
    let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = c == 5 && a == b;
    let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified
    //|~ HELP for further information visit
    //|~ SUGGESTION let _ = c == 5 && a == b;
    let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug
    //|~ HELP for further information visit
    //|~ HELP this expression can be optimized out
    //|~ HELP it would look like the following
    //|~ SUGGESTION let _ = false;
    let _ = a > b && a == b;

    let _ = a != b || !(a != b || c == d);
}
<|endoftext|>


<commit_before><commit_msg>More detailed message<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ffi::OsString;

use common::ui::UI;

use error::Result;

const LAUNCH_CMD: &'static str = "hab-launch";
const LAUNCH_CMD_ENVVAR: &'static str = "HAB_LAUNCH_BINARY";
const LAUNCH_PKG_IDENT: &'static str = "core/hab-launch";

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    inner::start(ui, args)
}

#[cfg(not(target_os = "macos"))]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use super::{LAUNCH_CMD, LAUNCH_CMD_ENVVAR, LAUNCH_PKG_IDENT};
    use error::{Error, Result};
    use exec;
    use VERSION;

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(LAUNCH_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let version: Vec<&str> = VERSION.split("/").collect();
                let cmd =
                    exec::command_from_min_pkg(
                        ui,
                        LAUNCH_CMD,
                        &PackageIdent::from_str(&format!("{}/{}", LAUNCH_PKG_IDENT, version[0]))?,
                        &default_cache_key_path(None),
                        0,
                    )?;
                PathBuf::from(cmd)
            }
        };
        if let Some(cmd) = find_command(&command) {
            Ok(process::become_command(cmd, args)?)
        } else {
            Err(Error::ExecCommandNotFound(command))
        }
    }
}

#[cfg(target_os = "macos")]
mod inner {
    use std::env;
    use std::ffi::OsString;

    use common::ui::UI;

    use error::{Error, Result};

    pub fn start(ui: &mut UI, _args: Vec<OsString>) -> Result<()> {
        let subcmd = env::args().nth(1).unwrap_or("<unknown>".to_string());
        ui.warn(
            "Launching a native Supervisor on this operating system is not yet supported. \
            Try running this command again on 64-bit Linux or Windows.",
        )?;
        ui.br()?;
        Err(Error::SubcommandNotSupported(subcmd))
    }
}
<commit_msg>Use proper pkg ident for launcher<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ffi::OsString;

use common::ui::UI;

use error::Result;

const LAUNCH_CMD: &'static str = "hab-launch";
const LAUNCH_CMD_ENVVAR: &'static str = "HAB_LAUNCH_BINARY";
const LAUNCH_PKG_IDENT: &'static str = "core/hab-launcher";

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    inner::start(ui, args)
}

#[cfg(not(target_os = "macos"))]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use super::{LAUNCH_CMD, LAUNCH_CMD_ENVVAR, LAUNCH_PKG_IDENT};
    use error::{Error, Result};
    use exec;
    use VERSION;

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(LAUNCH_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let version: Vec<&str> = VERSION.split("/").collect();
                let cmd =
                    exec::command_from_min_pkg(
                        ui,
                        LAUNCH_CMD,
                        &PackageIdent::from_str(&format!("{}/{}", LAUNCH_PKG_IDENT, version[0]))?,
                        &default_cache_key_path(None),
                        0,
                    )?;
                PathBuf::from(cmd)
            }
        };
        if let Some(cmd) = find_command(&command) {
            Ok(process::become_command(cmd, args)?)
        } else {
            Err(Error::ExecCommandNotFound(command))
        }
    }
}

#[cfg(target_os = "macos")]
mod inner {
    use std::env;
    use std::ffi::OsString;

    use common::ui::UI;

    use error::{Error, Result};

    pub fn start(ui: &mut UI, _args: Vec<OsString>) -> Result<()> {
        let subcmd = env::args().nth(1).unwrap_or("<unknown>".to_string());
        ui.warn(
            "Launching a native Supervisor on this operating system is not yet supported. \
            Try running this command again on 64-bit Linux or Windows.",
        )?;
        ui.br()?;
        Err(Error::SubcommandNotSupported(subcmd))
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate clap;
extern crate env_logger;
extern crate habitat_common as common;
extern crate habitat_core as hcore;
extern crate habitat_pkg_export_docker as export_docker;
extern crate habitat_pkg_export_kubernetes as export_k8s;
extern crate handlebars;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_json;
extern crate url;

extern crate failure;
#[macro_use]
extern crate failure_derive;

mod chart;
mod chartfile;
mod deps;
mod error;
mod maintainer;
mod values;

use std::result;
use std::str::FromStr;

use clap::Arg;

use common::ui::{UIWriter, UI};
use export_docker::Result;
use export_k8s::Cli;
use hcore::PROGRAM_NAME;
use url::Url;

use chart::Chart;

fn main() {
    env_logger::init();
    let mut ui = UI::default_with_env();
    let m = cli().get_matches();
    debug!("clap cli args: {:?}", m);

    if let Err(e) = export_for_cli_matches(&mut ui, &m) {
        let _ = ui.fatal(e);
        std::process::exit(1)
    }
}

fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let chart = Chart::new_for_cli_matches(ui, matches)?;
    chart.generate()?;

    Ok(())
}

lazy_static! {
    pub static ref VERSION_HELP: String = format!(
        "Version of the chart to create (default: {{pkg_version}} if available, or {})",
        chartfile::DEFAULT_VERSION
    );
}

fn cli<'a, 'b>() -> clap::App<'a, 'b> {
    let name: &str = &*PROGRAM_NAME;
    let about = "Creates a Docker image and generates a Helm chart for the specified Habitat \
                 package.";

    Cli::new(name, about)
        .add_docker_args()
        .add_runtime_args()
        .add_secret_names_args()
        .add_bind_args()
        .app
        .arg(
            Arg::with_name("CHART")
                .value_name("CHART")
                .long("chart")
                .short("h")
                .help("Name of the chart to create, if different from the package name"),
        )
        .arg(
            Arg::with_name("VERSION")
                .value_name("VERSION")
                .short("V")
                .long("version")
                .validator(valid_version)
                .help(&VERSION_HELP),
        )
        .arg(
            Arg::with_name("DESCRIPTION")
                .value_name("DESCRIPTION")
                .long("desc")
                .help("A single-sentence description"),
        )
        .arg(
            Arg::with_name("KEYWORD")
                .value_name("KEYWORD")
                .long("keyword")
                .short("k")
                .multiple(true)
                .help("A keyword for this project"),
        )
        .arg(
            Arg::with_name("HOME")
                .value_name("URL")
                .long("home")
                .validator(valid_url)
                .help("The URL of the project's home page"),
        )
        .arg(
            Arg::with_name("ICON")
                .value_name("URL")
                .long("icon")
                .validator(valid_url)
                .help("A URL of an SVG or PNG image to be used as an icon"),
        )
        .arg(
            Arg::with_name("SOURCE")
                .value_name("URL")
                .long("source")
                .short("s")
                .multiple(true)
                .validator(valid_url)
                .help("A URL to the source code for the project"),
        )
        .arg(
            Arg::with_name("MAINTAINER")
                .value_name("MAINTAINER_SPEC")
                .long("maint")
                .short("m")
                .multiple(true)
                .validator(valid_maintainer)
                .help("A maintainer of the project, in the form of NAME,[EMAIL[,URL]]"),
        )
        .arg(
            Arg::with_name("DEPRECATED")
                .long("depr")
                .help("Mark this chart as deprecated"),
        )
        .arg(
            Arg::with_name("OPERATOR_VERSION")
                .value_name("OPERATOR_VERSION")
                .long("operator-version")
                .validator(valid_version)
                .help("Version of the Habitat operator to set as dependency")
                .default_value(deps::DEFAULT_OPERATOR_VERSION),
        )
        .arg(
            Arg::with_name("OUTPUTDIR")
                .value_name("OUTPUTDIR")
                .short("o")
                .long("output-dir")
                .help(
                    "The directory to put the chart directory under (default: current working \
                     directory)",
                ),
        )
        .arg(Arg::with_name("DOWNLOAD_DEPS").long("download-deps").help(
            "Whether to download dependencies. The Kubernetes Habitat Operator is the only \
             dependancy currently. (default: no)",
        ))
}

fn valid_version(val: String) -> result::Result<(), String> {
    let split: Vec<&str> = val.split(".").collect();
    if split.len() != 3 {
        return Err(format!("Version '{}' is not valid", &val));
    }

    for s in split {
        for c in s.chars() {
            if !c.is_digit(10) {
                return Err(format!("Version '{}' is not valid", &val));
            }
        }
    }

    Ok(())
}

fn valid_url(val: String) -> result::Result<(), String> {
    match Url::parse(&val) {
        Ok(_) => Ok(()),
        Err(_) => Err(format!("URL: '{}' is not valid", &val)),
    }
}

fn valid_maintainer(val: String) -> result::Result<(), String> {
    maintainer::Maintainer::from_str(&val)
        .map(|_| ())
        .map_err(|e| format!("{}", e))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_version() {
        valid_version("0.0.1".to_owned()).unwrap();
        valid_version("0.1.1".to_owned()).unwrap();
        valid_version("1.1.1".to_owned()).unwrap();
        valid_version("1.1.10".to_owned()).unwrap();
        valid_version("1.10.1".to_owned()).unwrap();
        valid_version("10.1.1".to_owned()).unwrap();

        assert!(valid_version("1".to_owned()).is_err());
        assert!(valid_version("1.1".to_owned()).is_err());
        assert!(valid_version("X".to_owned()).is_err());
        assert!(valid_version("1.2.Z".to_owned()).is_err());
        assert!(valid_version("1.1.1.1".to_owned()).is_err());
        assert!(valid_version("٣.7.৬".to_owned()).is_err());
    }

    #[test]
    fn test_maintainer() {
        valid_maintainer("name".to_owned()).unwrap();
        // Currently Email address is not checked for validity. See FIXME in Maintainer::from_str().
        valid_maintainer("name,email".to_owned()).unwrap();
        valid_maintainer("name,email,http://blah".to_owned()).unwrap();

        assert!(valid_maintainer("name,email,blah".to_owned()).is_err());
        assert!(valid_maintainer("name,email,http://blah,x".to_owned()).is_err());
    }
}
<commit_msg>pkg-export-helm: Fix a typo<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate clap;
extern crate env_logger;
extern crate habitat_common as common;
extern crate habitat_core as hcore;
extern crate habitat_pkg_export_docker as export_docker;
extern crate habitat_pkg_export_kubernetes as export_k8s;
extern crate handlebars;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_json;
extern crate url;

extern crate failure;
#[macro_use]
extern crate failure_derive;

mod chart;
mod chartfile;
mod deps;
mod error;
mod maintainer;
mod values;

use std::result;
use std::str::FromStr;

use clap::Arg;

use common::ui::{UIWriter, UI};
use export_docker::Result;
use export_k8s::Cli;
use hcore::PROGRAM_NAME;
use url::Url;

use chart::Chart;

fn main() {
    env_logger::init();
    let mut ui = UI::default_with_env();
    let m = cli().get_matches();
    debug!("clap cli args: {:?}", m);

    if let Err(e) = export_for_cli_matches(&mut ui, &m) {
        let _ = ui.fatal(e);
        std::process::exit(1)
    }
}

fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let chart = Chart::new_for_cli_matches(ui, matches)?;
    chart.generate()?;

    Ok(())
}

lazy_static! {
    pub static ref VERSION_HELP: String = format!(
        "Version of the chart to create (default: {{pkg_version}} if available, or {})",
        chartfile::DEFAULT_VERSION
    );
}

fn cli<'a, 'b>() -> clap::App<'a, 'b> {
    let name: &str = &*PROGRAM_NAME;
    let about = "Creates a Docker image and generates a Helm chart for the specified Habitat \
                 package.";

    Cli::new(name, about)
        .add_docker_args()
        .add_runtime_args()
        .add_secret_names_args()
        .add_bind_args()
        .app
        .arg(
            Arg::with_name("CHART")
                .value_name("CHART")
                .long("chart")
                .short("h")
                .help("Name of the chart to create, if different from the package name"),
        )
        .arg(
            Arg::with_name("VERSION")
                .value_name("VERSION")
                .short("V")
                .long("version")
                .validator(valid_version)
                .help(&VERSION_HELP),
        )
        .arg(
            Arg::with_name("DESCRIPTION")
                .value_name("DESCRIPTION")
                .long("desc")
                .help("A single-sentence description"),
        )
        .arg(
            Arg::with_name("KEYWORD")
                .value_name("KEYWORD")
                .long("keyword")
                .short("k")
                .multiple(true)
                .help("A keyword for this project"),
        )
        .arg(
            Arg::with_name("HOME")
                .value_name("URL")
                .long("home")
                .validator(valid_url)
                .help("The URL of the project's home page"),
        )
        .arg(
            Arg::with_name("ICON")
                .value_name("URL")
                .long("icon")
                .validator(valid_url)
                .help("A URL of an SVG or PNG image to be used as an icon"),
        )
        .arg(
            Arg::with_name("SOURCE")
                .value_name("URL")
                .long("source")
                .short("s")
                .multiple(true)
                .validator(valid_url)
                .help("A URL to the source code for the project"),
        )
        .arg(
            Arg::with_name("MAINTAINER")
                .value_name("MAINTAINER_SPEC")
                .long("maint")
                .short("m")
                .multiple(true)
                .validator(valid_maintainer)
                .help("A maintainer of the project, in the form of NAME,[EMAIL[,URL]]"),
        )
        .arg(
            Arg::with_name("DEPRECATED")
                .long("depr")
                .help("Mark this chart as deprecated"),
        )
        .arg(
            Arg::with_name("OPERATOR_VERSION")
                .value_name("OPERATOR_VERSION")
                .long("operator-version")
                .validator(valid_version)
                .help("Version of the Habitat operator to set as dependency")
                .default_value(deps::DEFAULT_OPERATOR_VERSION),
        )
        .arg(
            Arg::with_name("OUTPUTDIR")
                .value_name("OUTPUTDIR")
                .short("o")
                .long("output-dir")
                .help(
                    "The directory to put the chart directory under (default: current working \
                     directory)",
                ),
        )
        .arg(Arg::with_name("DOWNLOAD_DEPS").long("download-deps").help(
            "Whether to download dependencies. The Kubernetes Habitat Operator is the only \
             dependency currently. (default: no)",
        ))
}

fn valid_version(val: String) -> result::Result<(), String> {
    let split: Vec<&str> = val.split(".").collect();
    if split.len() != 3 {
        return Err(format!("Version '{}' is not valid", &val));
    }

    for s in split {
        for c in s.chars() {
            if !c.is_digit(10) {
                return Err(format!("Version '{}' is not valid", &val));
            }
        }
    }

    Ok(())
}

fn valid_url(val: String) -> result::Result<(), String> {
    match Url::parse(&val) {
        Ok(_) => Ok(()),
        Err(_) => Err(format!("URL: '{}' is not valid", &val)),
    }
}

fn valid_maintainer(val: String) -> result::Result<(), String> {
    maintainer::Maintainer::from_str(&val)
        .map(|_| ())
        .map_err(|e| format!("{}", e))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_version() {
        valid_version("0.0.1".to_owned()).unwrap();
        valid_version("0.1.1".to_owned()).unwrap();
        valid_version("1.1.1".to_owned()).unwrap();
        valid_version("1.1.10".to_owned()).unwrap();
        valid_version("1.10.1".to_owned()).unwrap();
        valid_version("10.1.1".to_owned()).unwrap();

        assert!(valid_version("1".to_owned()).is_err());
        assert!(valid_version("1.1".to_owned()).is_err());
        assert!(valid_version("X".to_owned()).is_err());
        assert!(valid_version("1.2.Z".to_owned()).is_err());
        assert!(valid_version("1.1.1.1".to_owned()).is_err());
        assert!(valid_version("٣.7.৬".to_owned()).is_err());
    }

    #[test]
    fn test_maintainer() {
        valid_maintainer("name".to_owned()).unwrap();
        // Currently Email address is not checked for validity. See FIXME in Maintainer::from_str().
        valid_maintainer("name,email".to_owned()).unwrap();
        valid_maintainer("name,email,http://blah".to_owned()).unwrap();

        assert!(valid_maintainer("name,email,blah".to_owned()).is_err());
        assert!(valid_maintainer("name,email,http://blah,x".to_owned()).is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate clap;
extern crate env_logger;
extern crate habitat_core as hcore;
extern crate habitat_common as common;
extern crate habitat_pkg_export_docker as export_docker;
extern crate habitat_pkg_export_kubernetes as export_k8s;
extern crate handlebars;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_json;

extern crate failure;

mod chart;
mod chartfile;
mod values;

use std::result;

use clap::Arg;

use common::ui::UI;
use export_docker::Result;
use export_k8s::Cli;
use hcore::PROGRAM_NAME;

use chart::Chart;

fn main() {
    env_logger::init();
    let mut ui = UI::default_with_env();
    let m = cli().get_matches();
    debug!("clap cli args: {:?}", m);

    if let Err(e) = export_for_cli_matches(&mut ui, &m) {
        let _ = ui.fatal(e);
        std::process::exit(1)
    }
}

fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let chart = Chart::new_for_cli_matches(ui, matches)?;
    chart.generate()?;

    Ok(())
}

fn cli<'a, 'b>() -> clap::App<'a, 'b> {
    let name: &str = &*PROGRAM_NAME;
    let about = "Creates a Docker image and generates a Helm chart for the specified Habitat \
                 package. Habitat operator must be deployed within the Kubernetes cluster before \
                 the generated chart can be installed.";

    Cli::new(name, about)
        .add_docker_args()
        .add_runtime_args()
        .add_secret_names_args()
        .add_bind_args()
        .app
        .arg(
            Arg::with_name("CHART")
                .value_name("CHART")
                .long("chart")
                .short("h")
                .help(
                    "Name of the chart to create, if different from the package name",
                ),
        )
        .arg(
            Arg::with_name("VERSION")
                .value_name("VERSION")
                .long("version")
                .validator(valid_version)
                // Keep the default version here in sync with chartfile::DEFAULT_VERSION
                .help("Version of the chart to create (default: 0.0.1)"),
        )
        .arg(
            Arg::with_name("DESCRIPTION")
                .value_name("DESCRIPTION")
                .long("desc")
                .help("A single-sentence description"),
        )
}

fn valid_version(val: String) -> result::Result<(), String> {
    let split: Vec<&str> = val.split(".").collect();
    if split.len() != 3 {
        return Err(format!("Version '{}' is not valid", &val));
    }

    for s in split {
        for c in s.chars() {
            if !c.is_digit(10) {
                return Err(format!("Version '{}' is not valid", &val));
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_version() {
        valid_version("0.0.1".to_owned()).unwrap();
        valid_version("0.1.1".to_owned()).unwrap();
        valid_version("1.1.1".to_owned()).unwrap();
        valid_version("1.1.10".to_owned()).unwrap();
        valid_version("1.10.1".to_owned()).unwrap();
        valid_version("10.1.1".to_owned()).unwrap();

        assert!(valid_version("1".to_owned()).is_err());
        assert!(valid_version("1.1".to_owned()).is_err());
        assert!(valid_version("X".to_owned()).is_err());
        assert!(valid_version("1.2.Z".to_owned()).is_err());
        assert!(valid_version("1.1.1.1".to_owned()).is_err());
        assert!(valid_version("٣.7.৬".to_owned()).is_err());
    }
}
<commit_msg>pkg-export-helm: Add short option for --version<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate clap;
extern crate env_logger;
extern crate habitat_core as hcore;
extern crate habitat_common as common;
extern crate habitat_pkg_export_docker as export_docker;
extern crate habitat_pkg_export_kubernetes as export_k8s;
extern crate handlebars;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_json;

extern crate failure;

mod chart;
mod chartfile;
mod values;

use std::result;

use clap::Arg;

use common::ui::UI;
use export_docker::Result;
use export_k8s::Cli;
use hcore::PROGRAM_NAME;

use chart::Chart;

fn main() {
    env_logger::init();
    let mut ui = UI::default_with_env();
    let m = cli().get_matches();
    debug!("clap cli args: {:?}", m);

    if let Err(e) = export_for_cli_matches(&mut ui, &m) {
        let _ = ui.fatal(e);
        std::process::exit(1)
    }
}

fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let chart = Chart::new_for_cli_matches(ui, matches)?;
    chart.generate()?;

    Ok(())
}

fn cli<'a, 'b>() -> clap::App<'a, 'b> {
    let name: &str = &*PROGRAM_NAME;
    let about = "Creates a Docker image and generates a Helm chart for the specified Habitat \
                 package. Habitat operator must be deployed within the Kubernetes cluster before \
                 the generated chart can be installed.";

    Cli::new(name, about)
        .add_docker_args()
        .add_runtime_args()
        .add_secret_names_args()
        .add_bind_args()
        .app
        .arg(
            Arg::with_name("CHART")
                .value_name("CHART")
                .long("chart")
                .short("h")
                .help(
                    "Name of the chart to create, if different from the package name",
                ),
        )
        .arg(
            Arg::with_name("VERSION")
                .value_name("VERSION")
                .short("V")
                .long("version")
                .validator(valid_version)
                // Keep the default version here in sync with chartfile::DEFAULT_VERSION
                .help("Version of the chart to create (default: 0.0.1)"),
        )
        .arg(
            Arg::with_name("DESCRIPTION")
                .value_name("DESCRIPTION")
                .long("desc")
                .help("A single-sentence description"),
        )
}

fn valid_version(val: String) -> result::Result<(), String> {
    let split: Vec<&str> = val.split(".").collect();
    if split.len() != 3 {
        return Err(format!("Version '{}' is not valid", &val));
    }

    for s in split {
        for c in s.chars() {
            if !c.is_digit(10) {
                return Err(format!("Version '{}' is not valid", &val));
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_version() {
        valid_version("0.0.1".to_owned()).unwrap();
        valid_version("0.1.1".to_owned()).unwrap();
        valid_version("1.1.1".to_owned()).unwrap();
        valid_version("1.1.10".to_owned()).unwrap();
        valid_version("1.10.1".to_owned()).unwrap();
        valid_version("10.1.1".to_owned()).unwrap();

        assert!(valid_version("1".to_owned()).is_err());
        assert!(valid_version("1.1".to_owned()).is_err());
        assert!(valid_version("X".to_owned()).is_err());
        assert!(valid_version("1.2.Z".to_owned()).is_err());
        assert!(valid_version("1.1.1.1".to_owned()).is_err());
        assert!(valid_version("٣.7.৬".to_owned()).is_err());
    }
}
<|endoftext|>


<commit_before>use std;
use std::path::Path;

use aes;
use aes::{Aes128, MODE};
use aes::BLOCK_SIZE;
use aes::unpad_inplace;

use byteorder::{ByteOrder, NativeEndian};

use set1::decrypt_single_xor;

use mersenne;
use mersenne::MersenneTwister;

use serialize::from_base64;
use serialize::from_base64_lines;

use unstable_features::all_bytes;

use xor::XOR;

use rand;
use rand::Rng;

use helper::ceil_div;

use errors::*;

struct Server17 {
    key: Vec<u8>
}

impl Server17 {
    fn new() -> Self {
        Self { key: random_block() }
    }

    fn get_session_token(&self) -> Result<(Vec<u8>, Vec<u8>)> {
        let inputs = [
            "MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=",
            "MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=",
            "MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==",
            "MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==",
            "MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl",
            "MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==",
            "MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==",
            "MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=",
            "MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=",
            "MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93",
        ];
        let mut rng = rand::thread_rng();
        let input_index = rng.gen_range(0, 10);
        let input = from_base64(inputs[input_index]).unwrap();
        let iv = random_block();
        let ciphertext = input.encrypt(&self.key, Some(&iv), MODE::CBC)?;
        Ok((ciphertext, iv))
    }

    fn is_padding_valid(&self, iv: &[u8], ciphertext: &[u8]) -> Result<bool> {
        match ciphertext.decrypt(&self.key, Some(iv), MODE::CBC) {
            Err(aes::Error(aes::ErrorKind::InvalidPadding, _)) => Ok(false),
            Err(e) => Err(e.into()),
            _ => Ok(true),
        }
    }

    fn verify_solution(&self, cleartext: &[u8], iv: &[u8], ciphertext: &[u8]) -> Result<()> {
        compare(cleartext, &ciphertext.decrypt(&self.key, Some(&iv), MODE::CBC)?)
    }
}

fn random_block() -> Vec<u8> {
    let mut rng = rand::thread_rng();
    rng.gen_iter().take(BLOCK_SIZE).collect()
}

fn matasano3_17() -> Result<()> {
    let server = Server17::new();
    let (ciphertext, iv) = server.get_session_token()?;
    let mut cleartext = vec![0; ciphertext.len()];
    let mut prev = iv.clone();
    for (block_count, block) in ciphertext.chunks(BLOCK_SIZE).enumerate() {
        let block_offset = block_count * BLOCK_SIZE;
        for i in (0..BLOCK_SIZE).rev() {
            let padding = (BLOCK_SIZE - i) as u8;
            prev[i + 1..].xor_inplace(&[(padding - 1) ^ padding]);
            //Awaits replacement for range_inclusive
            for u in all_bytes() {
                prev[i] ^= u;
                if server.is_padding_valid(&prev, block)? && (i < BLOCK_SIZE - 1 || {
                    prev[i - 1] ^= 1;
                    let result = server.is_padding_valid(&prev, block)?;
                    prev[i - 1] ^= 1;
                    result
                }) {
                    cleartext[block_offset + i] = padding ^ u;
                    break;
                }
                prev[i] ^= u;
            }
        }
        prev = block.to_vec();
    }
    unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
    server.verify_solution(&cleartext, &ciphertext, &iv)
}

fn matasano3_18() -> Result<()> {
    let ciphertext =
        from_base64("L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ==")?;
    let cleartext = ciphertext.decrypt(b"YELLOW SUBMARINE", None, MODE::CTR)?;
    compare(
        b"Yo, VIP Let's kick it Ice, Ice, baby Ice, Ice, baby ".as_ref(),
        &cleartext,
    )
}

fn matasano3_19_20(input_file: &Path) -> Result<()> {
    let cleartexts = from_base64_lines(input_file)?;
    let secret_key = random_block();
    let ciphertexts = cleartexts
        .iter()
        .map(|c| {
            c.encrypt(&secret_key, None, MODE::CTR)
                .map_err(|err| err.into())
        })
        .collect::<Result<Vec<Vec<u8>>>>()?;
    let size = ciphertexts.iter().map(|c| c.len()).min().unwrap();
    let mut transposed_blocks: Vec<Vec<u8>> = (0..size)
        .map(|_| Vec::with_capacity(ciphertexts.len()))
        .collect();
    for ciphertext in ciphertexts {
        for (&u, bt) in ciphertext[..size].iter().zip(transposed_blocks.iter_mut()) {
            bt.push(u);
        }
    }
    let key = transposed_blocks
        .iter()
        .map(|b| decrypt_single_xor(b))
        .collect::<Vec<u8>>();
    //TODO: The first entry of the recovered key is wrong because the distribution of first letters
    //of sentences is very different from the overall distribution of letters in a text.
    compare(
        &vec![0; size].encrypt(&secret_key, None, MODE::CTR)?[1..],
        &key[1..],
    ) // encrypt or decrypt?
}

fn matasano3_21() -> Result<()> {
    let mt = MersenneTwister::initialize(1);
    compare(
        vec![
            1_791_095_845,
            4_282_876_139,
            3_093_770_124,
            4_005_303_368,
            491_263,
            550_290_313,
            1_298_508_491,
            4_290_846_341,
            630_311_759,
            1_013_994_432,
        ],
        mt.take(10).collect::<Vec<u32>>(),
    )
}

fn matasano3_22() -> Result<()> {
    let mut rng = rand::thread_rng();
    let seed: u16 = rng.gen();
    let mut mt = MersenneTwister::initialize(u32::from(seed));
    compare(
        Some(u32::from(seed)),
        mersenne::crack_seed_from_nth(mt.nth(0).unwrap(), 0, 0..(u32::from(std::u16::MAX))),
    )
}

fn matasano3_23() -> Result<()> {
    let mut rng = rand::thread_rng();
    let seed = rng.gen();
    let mut mt = MersenneTwister::initialize(seed);
    let mut state = [0; mersenne::STATE_SIZE];
    for entry in state.iter_mut() {
        *entry = mersenne::untemper(mt.next().unwrap());
    }
    let mut mt_clone = MersenneTwister::initialize_with_state(state);
    for _ in 0..mersenne::STATE_SIZE {
        compare(mt.next(), mt_clone.next())?;
    }
    Ok(())
}

fn matasano3_24() -> Result<()> {
    let mut rng = rand::thread_rng();
    let prefix_len: u8 = rng.gen();
    let cleartext = {
        let mut v: Vec<u8> = rng.gen_iter().take(prefix_len as usize).collect();
        v.extend_from_slice(&[b'A'; 14]);
        v
    };
    let seed: u16 = rng.gen();
    let mt = MersenneTwister::initialize(u32::from(seed));

    let mut ciphertext: Vec<u8> = Vec::new();
    let buffer = &mut [0u8; 4];

    for (c, m) in cleartext.chunks(4).zip(mt) {
        //Get underlying bytes from u32 value
        <NativeEndian as ByteOrder>::write_u32(buffer, m);
        ciphertext.append(&mut c.xor(buffer));
    }

    let (used_random_numbers_count, _) = ceil_div(ciphertext.len(), 4);
    let index = used_random_numbers_count - 2;
    // To recover the seed, we use the fact that the block ciphertext[4*index..4*(index+1)] was
    // encrypted with the index-th random number (counting as always from 0). As we also know the
    // plaintext at this position we can recover the random number.
    let random_number = <NativeEndian as ByteOrder>::read_u32(
        &ciphertext[4 * index..4 * (index + 1)].xor(&[b'A'; 4]),
    );
    compare(
        Some(u32::from(seed)),
        mersenne::crack_seed_from_nth(random_number, index, 0..(u32::from(std::u16::MAX))),
    )
}

pub fn run() {
    println!("Set 3");
    run_exercise(matasano3_17, 17);
    run_exercise(matasano3_18, 18);
    run_exercise(|| matasano3_19_20(Path::new("data/19.txt")), 19);
    run_exercise(|| matasano3_19_20(Path::new("data/20.txt")), 20);
    run_exercise(matasano3_21, 21);
    run_exercise(matasano3_22, 22);
    run_exercise(matasano3_23, 23);
    run_exercise(matasano3_24, 24);
}
<commit_msg>Fix argument order<commit_after>use std;
use std::path::Path;

use aes;
use aes::{Aes128, MODE};
use aes::BLOCK_SIZE;
use aes::unpad_inplace;

use byteorder::{ByteOrder, NativeEndian};

use set1::decrypt_single_xor;

use mersenne;
use mersenne::MersenneTwister;

use serialize::from_base64;
use serialize::from_base64_lines;

use unstable_features::all_bytes;

use xor::XOR;

use rand;
use rand::Rng;

use helper::ceil_div;

use errors::*;

struct Server17 {
    key: Vec<u8>
}

impl Server17 {
    fn new() -> Self {
        Self { key: random_block() }
    }

    fn get_session_token(&self) -> Result<(Vec<u8>, Vec<u8>)> {
        let inputs = [
            "MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=",
            "MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=",
            "MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==",
            "MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==",
            "MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl",
            "MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==",
            "MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==",
            "MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=",
            "MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=",
            "MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93",
        ];
        let mut rng = rand::thread_rng();
        let input_index = rng.gen_range(0, 10);
        let input = from_base64(inputs[input_index]).unwrap();
        let iv = random_block();
        let ciphertext = input.encrypt(&self.key, Some(&iv), MODE::CBC)?;
        Ok((ciphertext, iv))
    }

    fn is_padding_valid(&self, iv: &[u8], ciphertext: &[u8]) -> Result<bool> {
        match ciphertext.decrypt(&self.key, Some(iv), MODE::CBC) {
            Err(aes::Error(aes::ErrorKind::InvalidPadding, _)) => Ok(false),
            Err(e) => Err(e.into()),
            _ => Ok(true),
        }
    }

    fn verify_solution(&self, cleartext: &[u8], iv: &[u8], ciphertext: &[u8]) -> Result<()> {
        compare(&ciphertext.decrypt(&self.key, Some(&iv), MODE::CBC)?[..], cleartext)
    }
}

fn random_block() -> Vec<u8> {
    let mut rng = rand::thread_rng();
    rng.gen_iter().take(BLOCK_SIZE).collect()
}

fn matasano3_17() -> Result<()> {
    let server = Server17::new();
    let (ciphertext, iv) = server.get_session_token()?;
    let mut cleartext = vec![0; ciphertext.len()];
    let mut prev = iv.clone();
    for (block_count, block) in ciphertext.chunks(BLOCK_SIZE).enumerate() {
        let block_offset = block_count * BLOCK_SIZE;
        for i in (0..BLOCK_SIZE).rev() {
            let padding = (BLOCK_SIZE - i) as u8;
            prev[i + 1..].xor_inplace(&[(padding - 1) ^ padding]);
            //Awaits replacement for range_inclusive
            for u in all_bytes() {
                prev[i] ^= u;
                if server.is_padding_valid(&prev, block)? && (i < BLOCK_SIZE - 1 || {
                    prev[i - 1] ^= 1;
                    let result = server.is_padding_valid(&prev, block)?;
                    prev[i - 1] ^= 1;
                    result
                }) {
                    cleartext[block_offset + i] = padding ^ u;
                    break;
                }
                prev[i] ^= u;
            }
        }
        prev = block.to_vec();
    }
    unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
    server.verify_solution(&cleartext, &iv, &ciphertext)
}

fn matasano3_18() -> Result<()> {
    let ciphertext =
        from_base64("L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ==")?;
    let cleartext = ciphertext.decrypt(b"YELLOW SUBMARINE", None, MODE::CTR)?;
    compare(
        b"Yo, VIP Let's kick it Ice, Ice, baby Ice, Ice, baby ".as_ref(),
        &cleartext,
    )
}

fn matasano3_19_20(input_file: &Path) -> Result<()> {
    let cleartexts = from_base64_lines(input_file)?;
    let secret_key = random_block();
    let ciphertexts = cleartexts
        .iter()
        .map(|c| {
            c.encrypt(&secret_key, None, MODE::CTR)
                .map_err(|err| err.into())
        })
        .collect::<Result<Vec<Vec<u8>>>>()?;
    let size = ciphertexts.iter().map(|c| c.len()).min().unwrap();
    let mut transposed_blocks: Vec<Vec<u8>> = (0..size)
        .map(|_| Vec::with_capacity(ciphertexts.len()))
        .collect();
    for ciphertext in ciphertexts {
        for (&u, bt) in ciphertext[..size].iter().zip(transposed_blocks.iter_mut()) {
            bt.push(u);
        }
    }
    let key = transposed_blocks
        .iter()
        .map(|b| decrypt_single_xor(b))
        .collect::<Vec<u8>>();
    //TODO: The first entry of the recovered key is wrong because the distribution of first letters
    //of sentences is very different from the overall distribution of letters in a text.
    compare(
        &vec![0; size].encrypt(&secret_key, None, MODE::CTR)?[1..],
        &key[1..],
    ) // encrypt or decrypt?
}

fn matasano3_21() -> Result<()> {
    let mt = MersenneTwister::initialize(1);
    compare(
        vec![
            1_791_095_845,
            4_282_876_139,
            3_093_770_124,
            4_005_303_368,
            491_263,
            550_290_313,
            1_298_508_491,
            4_290_846_341,
            630_311_759,
            1_013_994_432,
        ],
        mt.take(10).collect::<Vec<u32>>(),
    )
}

fn matasano3_22() -> Result<()> {
    let mut rng = rand::thread_rng();
    let seed: u16 = rng.gen();
    let mut mt = MersenneTwister::initialize(u32::from(seed));
    compare(
        Some(u32::from(seed)),
        mersenne::crack_seed_from_nth(mt.nth(0).unwrap(), 0, 0..(u32::from(std::u16::MAX))),
    )
}

fn matasano3_23() -> Result<()> {
    let mut rng = rand::thread_rng();
    let seed = rng.gen();
    let mut mt = MersenneTwister::initialize(seed);
    let mut state = [0; mersenne::STATE_SIZE];
    for entry in state.iter_mut() {
        *entry = mersenne::untemper(mt.next().unwrap());
    }
    let mut mt_clone = MersenneTwister::initialize_with_state(state);
    for _ in 0..mersenne::STATE_SIZE {
        compare(mt.next(), mt_clone.next())?;
    }
    Ok(())
}

fn matasano3_24() -> Result<()> {
    let mut rng = rand::thread_rng();
    let prefix_len: u8 = rng.gen();
    let cleartext = {
        let mut v: Vec<u8> = rng.gen_iter().take(prefix_len as usize).collect();
        v.extend_from_slice(&[b'A'; 14]);
        v
    };
    let seed: u16 = rng.gen();
    let mt = MersenneTwister::initialize(u32::from(seed));

    let mut ciphertext: Vec<u8> = Vec::new();
    let buffer = &mut [0u8; 4];

    for (c, m) in cleartext.chunks(4).zip(mt) {
        //Get underlying bytes from u32 value
        <NativeEndian as ByteOrder>::write_u32(buffer, m);
        ciphertext.append(&mut c.xor(buffer));
    }

    let (used_random_numbers_count, _) = ceil_div(ciphertext.len(), 4);
    let index = used_random_numbers_count - 2;
    // To recover the seed, we use the fact that the block ciphertext[4*index..4*(index+1)] was
    // encrypted with the index-th random number (counting as always from 0). As we also know the
    // plaintext at this position we can recover the random number.
    let random_number = <NativeEndian as ByteOrder>::read_u32(
        &ciphertext[4 * index..4 * (index + 1)].xor(&[b'A'; 4]),
    );
    compare(
        Some(u32::from(seed)),
        mersenne::crack_seed_from_nth(random_number, index, 0..(u32::from(std::u16::MAX))),
    )
}

pub fn run() {
    println!("Set 3");
    run_exercise(matasano3_17, 17);
    run_exercise(matasano3_18, 18);
    run_exercise(|| matasano3_19_20(Path::new("data/19.txt")), 19);
    run_exercise(|| matasano3_19_20(Path::new("data/20.txt")), 20);
    run_exercise(matasano3_21, 21);
    run_exercise(matasano3_22, 22);
    run_exercise(matasano3_23, 23);
    run_exercise(matasano3_24, 24);
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::SocketAddr;
use std::sync::{RwLock, Arc};

use futures::Future;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::core::target::Difficulty;
use handshake::Handshake;
use types::*;
use util::LOGGER;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
	Connected,
	Disconnected,
	Banned,
}

pub struct Peer {
	pub info: PeerInfo,
	proto: Box<Protocol>,
	state: Arc<RwLock<State>>,
}

unsafe impl Sync for Peer {}
unsafe impl Send for Peer {}

impl Peer {
	/// Initiates the handshake with another peer.
	pub fn connect(conn: TcpStream,
	               capab: Capabilities,
	               total_difficulty: Difficulty,
	               self_addr: SocketAddr,
	               hs: &Handshake)
	               -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let connect_peer = hs.connect(capab, total_difficulty, self_addr, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				 Peer {
				     info: info,
				     proto: Box::new(proto),
				     state: Arc::new(RwLock::new(State::Connected)),
				 }))
			});
		Box::new(connect_peer)
	}

	/// Accept a handshake initiated by another peer.
	pub fn accept(conn: TcpStream,
	              capab: Capabilities,
	              total_difficulty: Difficulty,
	              hs: &Handshake)
	              -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let hs_peer = hs.handshake(capab, total_difficulty, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				 Peer {
				     info: info,
				     proto: Box::new(proto),
				     state: Arc::new(RwLock::new(State::Connected)),
				 }))
			});
		Box::new(hs_peer)
	}

	/// Main peer loop listening for messages and forwarding to the rest of the
	/// system.
	pub fn run(&self,
	           conn: TcpStream,
	           na: Arc<NetAdapter>)
	           -> Box<Future<Item = (), Error = Error>> {

		let addr = self.info.addr;
		let state = self.state.clone();
		Box::new(self.proto.handle(conn, na).then(move |res| {
			// handle disconnection, standard disconnections aren't considered an error
			let mut state = state.write().unwrap();
			match res {
				Ok(_) => {
					*state = State::Disconnected;
					info!(LOGGER, "Client {} disconnected.", addr);
					Ok(())
				}
				Err(Error::Serialization(e)) => {
					*state = State::Banned;
					info!(LOGGER, "Client {} corrupted, ban.", addr);
					Err(Error::Serialization(e))
				}
				Err(_) => {
					*state = State::Disconnected;
					info!(LOGGER, "Client {} connection lost.", addr);
					Ok(())
				}
			}
		}))
	}

	/// Whether this peer is still connected.
	pub fn is_connected(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Connected
	}

	/// Whether this peer has been banned.
	pub fn is_banned(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Banned
	}

	/// Bytes sent and received by this peer to the remote peer.
	pub fn transmitted_bytes(&self) -> (u64, u64) {
		self.proto.transmitted_bytes()
	}

	pub fn send_ping(&self) -> Result<(), Error> {
		self.proto.send_ping()
	}

	/// Sends the provided block to the remote peer. The request may be dropped
	/// if the remote peer is known to already have the block.
	pub fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		// TODO do not send if the peer sent us the block in the first place
		self.proto.send_block(b)
	}

	pub fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.proto.send_header_request(locator)
	}

	pub fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		debug!(
			LOGGER,
			"Requesting block {} from peer {}.",
			h,
			self.info.addr
		);
		self.proto.send_block_request(h)
	}

	pub fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		debug!(LOGGER, "Asking {} for more peers.", self.info.addr);
		self.proto.send_peer_request(capab)
	}

	pub fn stop(&self) {
		self.proto.close();
	}
}
<commit_msg>Log connection errors<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::SocketAddr;
use std::sync::{RwLock, Arc};

use futures::Future;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::core::target::Difficulty;
use handshake::Handshake;
use types::*;
use util::LOGGER;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
	Connected,
	Disconnected,
	Banned,
}

pub struct Peer {
	pub info: PeerInfo,
	proto: Box<Protocol>,
	state: Arc<RwLock<State>>,
}

unsafe impl Sync for Peer {}
unsafe impl Send for Peer {}

impl Peer {
	/// Initiates the handshake with another peer.
	pub fn connect(conn: TcpStream,
	               capab: Capabilities,
	               total_difficulty: Difficulty,
	               self_addr: SocketAddr,
	               hs: &Handshake)
	               -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let connect_peer = hs.connect(capab, total_difficulty, self_addr, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				 Peer {
				     info: info,
				     proto: Box::new(proto),
				     state: Arc::new(RwLock::new(State::Connected)),
				 }))
			});
		Box::new(connect_peer)
	}

	/// Accept a handshake initiated by another peer.
	pub fn accept(conn: TcpStream,
	              capab: Capabilities,
	              total_difficulty: Difficulty,
	              hs: &Handshake)
	              -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let hs_peer = hs.handshake(capab, total_difficulty, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				 Peer {
				     info: info,
				     proto: Box::new(proto),
				     state: Arc::new(RwLock::new(State::Connected)),
				 }))
			});
		Box::new(hs_peer)
	}

	/// Main peer loop listening for messages and forwarding to the rest of the
	/// system.
	pub fn run(&self,
	           conn: TcpStream,
	           na: Arc<NetAdapter>)
	           -> Box<Future<Item = (), Error = Error>> {

		let addr = self.info.addr;
		let state = self.state.clone();
		Box::new(self.proto.handle(conn, na).then(move |res| {
			// handle disconnection, standard disconnections aren't considered an error
			let mut state = state.write().unwrap();
			match res {
				Ok(_) => {
					*state = State::Disconnected;
					info!(LOGGER, "Client {} disconnected.", addr);
					Ok(())
				}
				Err(Error::Serialization(e)) => {
					*state = State::Banned;
					info!(LOGGER, "Client {} corrupted, ban.", addr);
					Err(Error::Serialization(e))
				}
				Err(e) => {
					*state = State::Disconnected;
					info!(LOGGER, "Client {} connection lost: {:?}", addr, e);
					Ok(())
				}
			}
		}))
	}

	/// Whether this peer is still connected.
	pub fn is_connected(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Connected
	}

	/// Whether this peer has been banned.
	pub fn is_banned(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Banned
	}

	/// Bytes sent and received by this peer to the remote peer.
	pub fn transmitted_bytes(&self) -> (u64, u64) {
		self.proto.transmitted_bytes()
	}

	pub fn send_ping(&self) -> Result<(), Error> {
		self.proto.send_ping()
	}

	/// Sends the provided block to the remote peer. The request may be dropped
	/// if the remote peer is known to already have the block.
	pub fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		// TODO do not send if the peer sent us the block in the first place
		self.proto.send_block(b)
	}

	pub fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.proto.send_header_request(locator)
	}

	pub fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		debug!(
			LOGGER,
			"Requesting block {} from peer {}.",
			h,
			self.info.addr
		);
		self.proto.send_block_request(h)
	}

	pub fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		debug!(LOGGER, "Asking {} for more peers.", self.info.addr);
		self.proto.send_peer_request(capab)
	}

	pub fn stop(&self) {
		self.proto.close();
	}
}
<|endoftext|>


<commit_before>use filetime::{self, FileTime};
use lazy_static::lazy_static;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

static CARGO_INTEGRATION_TEST_DIR: &str = "cit";

lazy_static! {
    static ref GLOBAL_ROOT: PathBuf = {
        let mut path = t!(env::current_exe());
        path.pop(); // chop off exe name
        path.pop(); // chop off 'debug'

        // If `cargo test` is run manually then our path looks like
        // `target/debug/foo`, in which case our `path` is already pointing at
        // `target`. If, however, `cargo test --target $target` is used then the
        // output is `target/$target/debug/foo`, so our path is pointing at
        // `target/$target`. Here we conditionally pop the `$target` name.
        if path.file_name().and_then(|s| s.to_str()) != Some("target") {
            path.pop();
        }

        path.push(CARGO_INTEGRATION_TEST_DIR);
        path.mkdir_p();
        path
    };

    static ref TEST_ROOTS: Mutex<HashMap<String, PathBuf>> = Default::default();
}

// We need to give each test a unique id. The test name could serve this
// purpose, but the `test` crate doesn't have a way to obtain the current test
// name.[*] Instead, we used the `cargo-test-macro` crate to automatically
// insert an init function for each test that sets the test name in a thread
// local variable.
//
// [*] It does set the thread name, but only when running concurrently. If not
// running concurrently, all tests are run on the main thread.
thread_local! {
    static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
}

pub struct TestIdGuard {
    _private: (),
}

pub fn init_root() -> TestIdGuard {
    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);

    let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
    TEST_ID.with(|n| *n.borrow_mut() = Some(id));

    let guard = TestIdGuard { _private: () };

    let r = root();
    r.rm_rf();
    r.mkdir_p();

    guard
}

impl Drop for TestIdGuard {
    fn drop(&mut self) {
        TEST_ID.with(|n| *n.borrow_mut() = None);
    }
}

pub fn root() -> PathBuf {
    let id = TEST_ID.with(|n| {
        n.borrow().expect(
            "Tests must use the `#[cargo_test]` attribute in \
             order to be able to use the crate root.",
        )
    });
    GLOBAL_ROOT.join(&format!("t{}", id))
}

pub fn home() -> PathBuf {
    let mut path = root();
    path.push("home");
    path.mkdir_p();
    path
}

pub trait CargoPathExt {
    fn rm_rf(&self);
    fn mkdir_p(&self);

    fn move_into_the_past(&self) {
        self.move_in_time(|sec, nsec| (sec - 3600, nsec))
    }

    fn move_into_the_future(&self) {
        self.move_in_time(|sec, nsec| (sec + 3600, nsec))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32);

    fn is_symlink(&self) -> bool;
}

impl CargoPathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) {
        if self.exists() {
            if let Err(e) = remove_dir_all::remove_dir_all(self) {
                panic!("failed to remove {:?}: {:?}", self, e)
            }
        }
    }

    fn mkdir_p(&self) {
        fs::create_dir_all(self)
            .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> ((i64, u32)),
    {
        if self.is_file() {
            time_travel(self, &travel_amount);
        } else {
            recurse(self, &self.join("target"), &travel_amount);
        }

        fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> ((i64, u32)),
        {
            if p.is_file() {
                time_travel(p, travel_amount)
            } else if !p.starts_with(bad) {
                for f in t!(fs::read_dir(p)) {
                    let f = t!(f).path();
                    recurse(&f, bad, travel_amount);
                }
            }
        }

        fn time_travel<F>(path: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> ((i64, u32)),
        {
            let stat = t!(path.symlink_metadata());

            let mtime = FileTime::from_last_modification_time(&stat);

            let (sec, nsec) = travel_amount(mtime.unix_seconds(), mtime.nanoseconds());
            let newtime = FileTime::from_unix_time(sec, nsec);

            // Sadly change_file_times has a failure mode where a readonly file
            // cannot have its times changed on windows.
            do_op(path, "set file times", |path| {
                filetime::set_file_times(path, newtime, newtime)
            });
        }
    }

    fn is_symlink(&self) -> bool {
        fs::symlink_metadata(self)
            .map(|m| m.file_type().is_symlink())
            .unwrap_or(false)
    }
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));

            // Unix also requires the parent to not be readonly for example when
            // removing files
            let parent = path.parent().unwrap();
            let mut p = t!(parent.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(parent, p));

            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}

/// Get the filename for a library.
///
/// `kind` should be one of: "lib", "rlib", "staticlib", "dylib", "proc-macro"
///
/// For example, dynamic library named "foo" would return:
/// - macOS: "libfoo.dylib"
/// - Windows: "foo.dll"
/// - Unix: "libfoo.so"
pub fn get_lib_filename(name: &str, kind: &str) -> String {
    let prefix = get_lib_prefix(kind);
    let extension = get_lib_extension(kind);
    format!("{}{}.{}", prefix, name, extension)
}

pub fn get_lib_prefix(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "lib",
        "staticlib" | "dylib" | "proc-macro" => {
            if cfg!(windows) {
                ""
            } else {
                "lib"
            }
        }
        _ => unreachable!(),
    }
}

pub fn get_lib_extension(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "rlib",
        "staticlib" => {
            if cfg!(windows) {
                "lib"
            } else {
                "a"
            }
        }
        "dylib" | "proc-macro" => {
            if cfg!(windows) {
                "dll"
            } else if cfg!(target_os = "macos") {
                "dylib"
            } else {
                "so"
            }
        }
        _ => unreachable!(),
    }
}

/// Returns the sysroot as queried from rustc.
pub fn sysroot() -> String {
    let output = Command::new("rustc")
        .arg("--print=sysroot")
        .output()
        .expect("rustc to run");
    assert!(output.status.success());
    let sysroot = String::from_utf8(output.stdout).unwrap();
    sysroot.trim().to_string()
}
<commit_msg>Remove some needless parentheses now reported on nightly.<commit_after>use filetime::{self, FileTime};
use lazy_static::lazy_static;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

static CARGO_INTEGRATION_TEST_DIR: &str = "cit";

lazy_static! {
    static ref GLOBAL_ROOT: PathBuf = {
        let mut path = t!(env::current_exe());
        path.pop(); // chop off exe name
        path.pop(); // chop off 'debug'

        // If `cargo test` is run manually then our path looks like
        // `target/debug/foo`, in which case our `path` is already pointing at
        // `target`. If, however, `cargo test --target $target` is used then the
        // output is `target/$target/debug/foo`, so our path is pointing at
        // `target/$target`. Here we conditionally pop the `$target` name.
        if path.file_name().and_then(|s| s.to_str()) != Some("target") {
            path.pop();
        }

        path.push(CARGO_INTEGRATION_TEST_DIR);
        path.mkdir_p();
        path
    };

    static ref TEST_ROOTS: Mutex<HashMap<String, PathBuf>> = Default::default();
}

// We need to give each test a unique id. The test name could serve this
// purpose, but the `test` crate doesn't have a way to obtain the current test
// name.[*] Instead, we used the `cargo-test-macro` crate to automatically
// insert an init function for each test that sets the test name in a thread
// local variable.
//
// [*] It does set the thread name, but only when running concurrently. If not
// running concurrently, all tests are run on the main thread.
thread_local! {
    static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
}

pub struct TestIdGuard {
    _private: (),
}

pub fn init_root() -> TestIdGuard {
    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);

    let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
    TEST_ID.with(|n| *n.borrow_mut() = Some(id));

    let guard = TestIdGuard { _private: () };

    let r = root();
    r.rm_rf();
    r.mkdir_p();

    guard
}

impl Drop for TestIdGuard {
    fn drop(&mut self) {
        TEST_ID.with(|n| *n.borrow_mut() = None);
    }
}

pub fn root() -> PathBuf {
    let id = TEST_ID.with(|n| {
        n.borrow().expect(
            "Tests must use the `#[cargo_test]` attribute in \
             order to be able to use the crate root.",
        )
    });
    GLOBAL_ROOT.join(&format!("t{}", id))
}

pub fn home() -> PathBuf {
    let mut path = root();
    path.push("home");
    path.mkdir_p();
    path
}

pub trait CargoPathExt {
    fn rm_rf(&self);
    fn mkdir_p(&self);

    fn move_into_the_past(&self) {
        self.move_in_time(|sec, nsec| (sec - 3600, nsec))
    }

    fn move_into_the_future(&self) {
        self.move_in_time(|sec, nsec| (sec + 3600, nsec))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32);

    fn is_symlink(&self) -> bool;
}

impl CargoPathExt for Path {
    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) {
        if self.exists() {
            if let Err(e) = remove_dir_all::remove_dir_all(self) {
                panic!("failed to remove {:?}: {:?}", self, e)
            }
        }
    }

    fn mkdir_p(&self) {
        fs::create_dir_all(self)
            .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32),
    {
        if self.is_file() {
            time_travel(self, &travel_amount);
        } else {
            recurse(self, &self.join("target"), &travel_amount);
        }

        fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            if p.is_file() {
                time_travel(p, travel_amount)
            } else if !p.starts_with(bad) {
                for f in t!(fs::read_dir(p)) {
                    let f = t!(f).path();
                    recurse(&f, bad, travel_amount);
                }
            }
        }

        fn time_travel<F>(path: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            let stat = t!(path.symlink_metadata());

            let mtime = FileTime::from_last_modification_time(&stat);

            let (sec, nsec) = travel_amount(mtime.unix_seconds(), mtime.nanoseconds());
            let newtime = FileTime::from_unix_time(sec, nsec);

            // Sadly change_file_times has a failure mode where a readonly file
            // cannot have its times changed on windows.
            do_op(path, "set file times", |path| {
                filetime::set_file_times(path, newtime, newtime)
            });
        }
    }

    fn is_symlink(&self) -> bool {
        fs::symlink_metadata(self)
            .map(|m| m.file_type().is_symlink())
            .unwrap_or(false)
    }
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));

            // Unix also requires the parent to not be readonly for example when
            // removing files
            let parent = path.parent().unwrap();
            let mut p = t!(parent.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(parent, p));

            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}

/// Get the filename for a library.
///
/// `kind` should be one of: "lib", "rlib", "staticlib", "dylib", "proc-macro"
///
/// For example, dynamic library named "foo" would return:
/// - macOS: "libfoo.dylib"
/// - Windows: "foo.dll"
/// - Unix: "libfoo.so"
pub fn get_lib_filename(name: &str, kind: &str) -> String {
    let prefix = get_lib_prefix(kind);
    let extension = get_lib_extension(kind);
    format!("{}{}.{}", prefix, name, extension)
}

pub fn get_lib_prefix(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "lib",
        "staticlib" | "dylib" | "proc-macro" => {
            if cfg!(windows) {
                ""
            } else {
                "lib"
            }
        }
        _ => unreachable!(),
    }
}

pub fn get_lib_extension(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "rlib",
        "staticlib" => {
            if cfg!(windows) {
                "lib"
            } else {
                "a"
            }
        }
        "dylib" | "proc-macro" => {
            if cfg!(windows) {
                "dll"
            } else if cfg!(target_os = "macos") {
                "dylib"
            } else {
                "so"
            }
        }
        _ => unreachable!(),
    }
}

/// Returns the sysroot as queried from rustc.
pub fn sysroot() -> String {
    let output = Command::new("rustc")
        .arg("--print=sysroot")
        .output()
        .expect("rustc to run");
    assert!(output.status.success());
    let sysroot = String::from_utf8(output.stdout).unwrap();
    sysroot.trim().to_string()
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.45";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        let _p = pushd("crates/ruma")?;
        cmd!("rustup run {MSRV} cargo build --features full").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run stable cargo test --workspace").run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --no-default-features").run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --all-features").run(),
            cmd!("rustup run stable cargo test -p ruma-client-api --all-features").run(),
            cmd!("rustup run stable cargo check -p ruma-client --no-default-features").run(),
            cmd!("rustup run stable cargo check -p ruma-client --all-features").run(),
        ]
        .into_iter()
        .collect()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run nightly cargo fmt -- --check").run(),
            cmd!("rustup run nightly cargo ruma-clippy -D warnings").run(),
            cmd!("rustup run nightly cargo clippy -p ruma-client --all-targets -- -D warnings")
                .run(),
        ]
        .into_iter()
        .collect()
    }
}
<commit_msg>ci: Clean up<commit_after>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.45";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        let _p = pushd("crates/ruma")?;
        cmd!("rustup run {MSRV} cargo build --features full").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        // 1. Make sure everything compiles
        cmd!("rustup run stable cargo check --workspace --all-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-client --no-default-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-identifiers --no-default-features").run()?;

        // 2. Run tests
        cmd!("rustup run stable cargo test --workspace").run()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        let fmt_res = cmd!("rustup run nightly cargo fmt -- --check").run();
        let clippy_res = cmd!("rustup run nightly cargo ruma-clippy -D warnings").run();
        fmt_res.or(clippy_res)
    }
}
<|endoftext|>


<commit_before>extern crate crc;
extern crate ci_capnp;

use std::io;
use std::process;

use std::io::Read;

use ci_capnp::FileEntry;

const PROG: &str = "../target/debug/ci-gen";

#[derive(Debug)]
struct TestEntry {
    crc: u32,
    entry: FileEntry,
}

fn entries(name: &str) -> io::Result<Vec<TestEntry>> {
    let mut prog = process::Command::new(PROG)
        .arg("-h")
        .arg("capnp")
        .arg(name)
        .stdin(process::Stdio::null())
        .stdout(process::Stdio::piped())
        .stderr(process::Stdio::inherit())
        .spawn()?;

    let mut res = Vec::new();

    {
        let mut out = prog.stdout.as_mut().unwrap();
        loop {
            let entry: FileEntry = match ci_capnp::read_entry(&mut out).unwrap() {
                Some(x) => x,
                None => break,
            };

            assert!(entry.content_follows);

            let mut limited = out.take(entry.len);
            let mut crc = 0;
            loop {
                let mut buf = [0u8; 4096];
                let found = limited.read(&mut buf)?;
                if 0 == found {
                    break;
                }

                crc = crc::crc32::update(crc, &crc::crc32::CASTAGNOLI_TABLE, &buf[0..found]);
            }

            res.push(TestEntry {
                crc,
                entry
            });
        }
    }

    assert!(prog.wait()?.success());

    res.sort_by(|left, right| {
        use std::cmp::Ordering;
        let left = &left.entry.paths;
        let right = &right.entry.paths;
        match left.len().cmp(&right.len()) {
            Ordering::Equal => {},
            other => return other,
        };

        for i in 0..left.len() {
            match left[i].cmp(&right[i]) {
                Ordering::Equal => {},
                other => return other,
            }
        }

        return Ordering::Equal;
    });

    Ok(res)
}

struct SimpleTest {
    paths: &'static [&'static str],
    normal_file: bool,
    crc: u32,
    len: u64,
}

const SIMPLE_EXPECTATIONS: &[SimpleTest] = &[
    SimpleTest { paths: &["a/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/b/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/b/c/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/bar"], normal_file: true, crc: 0xe3069283, len: 9 },
    SimpleTest { paths: &["foo"], normal_file: true, crc: 0xe3069283, len: 9 },
];

fn dump(actual: &[TestEntry]) {
    for item in actual {
        println!("{} {} {} {:?}", item.entry.normal_file, item.entry.len, item.crc, item.entry.paths);
    }
}

fn check_simple(path: &str, extra_path_component: Option<&str>) {
    let res = entries(path).unwrap();
    if res.len() != SIMPLE_EXPECTATIONS.len() {
        dump(&res);
        panic!("wrong number of entries: {} should be {}", res.len(), SIMPLE_EXPECTATIONS.len());
    }

    for i in 0..SIMPLE_EXPECTATIONS.len() {
        let exp = &SIMPLE_EXPECTATIONS[i];
        let act = &res[i];
        let mut exp_paths = exp.paths.iter().map(|x| x.to_string()).collect::<Vec<String>>();
        if let Some(component) = extra_path_component {
            exp_paths.push(component.to_string());
        }
        exp_paths.push(path.to_string());
        assert_eq!(exp_paths, act.entry.paths);
        assert_eq!(exp.normal_file, act.entry.normal_file);
        assert_eq!(exp.crc, act.crc, "{:08x} != {:08x}", exp.crc, act.crc);
        assert_eq!(exp.len, act.entry.len);
    }
}

fn check_byte_flip(path: &str, extra_path_component: Option<&str>) {
    let res = entries(path).unwrap();
    println!("{:?}", res);
    assert_eq!(2, res.len());
}

#[test]
fn simple_tar() {
    check_simple("tests/simple.tar", None)
}
#[test]
fn simple_tar_bz2() {
    check_simple("tests/simple.tar.bz2", Some("tests/simple.tar"))
}
#[test]
fn simple_tar_gz() {
    check_simple("tests/simple.tar.gz", Some("tests/simple.tar"))
}
#[test]
fn simple_tar_xz() {
    check_simple("tests/simple.tar.xz", Some("tests/simple.tar"))
}
#[test]
fn simple_zip() {
    check_simple("tests/simple.zip", None)
}

#[test]
fn byte_flip_tar() {
    check_byte_flip("tests/byte_flip.tar", None)
}
#[test]
fn byte_flip_tar_bz2() {
    check_byte_flip("tests/byte_flip.tar.bz2", Some("tests/byte_flip.tar"))
}
#[test]
fn byte_flip_tar_gz() {
    check_byte_flip("tests/byte_flip.tar.gz", Some("tests/byte_flip.tar"))
}
#[test]
fn byte_flip_tar_xz() {
    check_byte_flip("tests/byte_flip.tar.xz", Some("tests/byte_flip.tar"))
}
#[test]
fn byte_flip_zip() {
    check_byte_flip("tests/byte_flip.zip", None)
}<commit_msg>xz and tar are failing in a reasonable way<commit_after>extern crate crc;
extern crate ci_capnp;

use std::io;
use std::process;

use std::io::Read;

use ci_capnp::FileEntry;

const PROG: &str = "../target/debug/ci-gen";

#[derive(Debug)]
struct TestEntry {
    crc: u32,
    entry: FileEntry,
}

fn entries(name: &str) -> io::Result<Vec<TestEntry>> {
    let mut prog = process::Command::new(PROG)
        .arg("-h")
        .arg("capnp")
        .arg(name)
        .stdin(process::Stdio::null())
        .stdout(process::Stdio::piped())
        .stderr(process::Stdio::inherit())
        .spawn()?;

    let mut res = Vec::new();

    {
        let mut out = prog.stdout.as_mut().unwrap();
        loop {
            let entry: FileEntry = match ci_capnp::read_entry(&mut out).unwrap() {
                Some(x) => x,
                None => break,
            };

            assert!(entry.content_follows);

            let mut limited = out.take(entry.len);
            let mut crc = 0;
            loop {
                let mut buf = [0u8; 4096];
                let found = limited.read(&mut buf)?;
                if 0 == found {
                    break;
                }

                crc = crc::crc32::update(crc, &crc::crc32::CASTAGNOLI_TABLE, &buf[0..found]);
            }

            res.push(TestEntry {
                crc,
                entry
            });
        }
    }

    assert!(prog.wait()?.success());

    res.sort_by(|left, right| {
        use std::cmp::Ordering;
        let left = &left.entry.paths;
        let right = &right.entry.paths;
        match left.len().cmp(&right.len()) {
            Ordering::Equal => {},
            other => return other,
        };

        for i in 0..left.len() {
            match left[i].cmp(&right[i]) {
                Ordering::Equal => {},
                other => return other,
            }
        }

        return Ordering::Equal;
    });

    Ok(res)
}

struct SimpleTest {
    paths: &'static [&'static str],
    normal_file: bool,
    crc: u32,
    len: u64,
}

const SIMPLE_EXPECTATIONS: &[SimpleTest] = &[
    SimpleTest { paths: &["a/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/b/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/b/c/"], normal_file: false, crc: 0, len: 0 },
    SimpleTest { paths: &["a/bar"], normal_file: true, crc: 0xe3069283, len: 9 },
    SimpleTest { paths: &["foo"], normal_file: true, crc: 0xe3069283, len: 9 },
];

fn dump(actual: &[TestEntry]) {
    for item in actual {
        println!("{} {} {} {:?}", item.entry.normal_file, item.entry.len, item.crc, item.entry.paths);
    }
}

fn check_simple(path: &str, extra_path_component: Option<&str>) {
    let res = entries(path).unwrap();
    if res.len() != SIMPLE_EXPECTATIONS.len() {
        dump(&res);
        panic!("wrong number of entries: {} should be {}", res.len(), SIMPLE_EXPECTATIONS.len());
    }

    for i in 0..SIMPLE_EXPECTATIONS.len() {
        let exp = &SIMPLE_EXPECTATIONS[i];
        let act = &res[i];
        let mut exp_paths = exp.paths.iter().map(|x| x.to_string()).collect::<Vec<String>>();
        if let Some(component) = extra_path_component {
            exp_paths.push(component.to_string());
        }
        exp_paths.push(path.to_string());
        assert_eq!(exp_paths, act.entry.paths);
        assert_eq!(exp.normal_file, act.entry.normal_file);
        assert_eq!(exp.crc, act.crc, "{:08x} != {:08x}", exp.crc, act.crc);
        assert_eq!(exp.len, act.entry.len);
    }
}

fn check_byte_flip(path: &str, extra_path_component: Option<&str>) {
    let res = entries(path).unwrap();
    dump(&res);
    assert_eq!(2, res.len());
}

#[test]
fn simple_tar() {
    check_simple("tests/simple.tar", None)
}
#[test]
fn simple_tar_bz2() {
    check_simple("tests/simple.tar.bz2", Some("tests/simple.tar"))
}
#[test]
fn simple_tar_gz() {
    check_simple("tests/simple.tar.gz", Some("tests/simple.tar"))
}
#[test]
fn simple_tar_xz() {
    check_simple("tests/simple.tar.xz", Some("tests/simple.tar"))
}
#[test]
fn simple_zip() {
    check_simple("tests/simple.zip", None)
}

/// tar has no error checking, and file data gets corrupted, so we don't detect this.
#[test]
fn byte_flip_tar() {
    let entries = entries("tests/byte_flip.tar").unwrap();
    assert_eq!(2, entries.len());
    // this crc should be correct
    assert_eq!(2806881067, entries[0].crc);

    // this crc should be wrong...
    assert_eq!(3502720051, entries[1].crc);
}
#[test]
fn byte_flip_tar_bz2() {
    check_byte_flip("tests/byte_flip.tar.bz2", Some("tests/byte_flip.tar"))
}
#[test]
fn byte_flip_tar_gz() {
    check_byte_flip("tests/byte_flip.tar.gz", Some("tests/byte_flip.tar"))
}
#[test]
fn byte_flip_tar_xz() {
    let test_path = "tests/byte_flip.tar.xz";
    let entries = entries(test_path).unwrap();
    assert_eq!(1, entries.len());
    assert_eq!(1, entries[0].entry.paths.len());
    assert_eq!(test_path, entries[0].entry.paths[0]);
}
#[test]
fn byte_flip_zip() {
    check_byte_flip("tests/byte_flip.zip", None)
}<|endoftext|>


<commit_before>#[macro_use] extern crate radeco_lib;
extern crate r2pipe;

use std::path::{Path, PathBuf};
use std::fs::{self, File};

use r2pipe::r2::R2;

use radeco_lib::frontend::containers::RadecoModule;
use radeco_lib::analysis::sccp::sccp;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::middle::{dce};
use radeco_lib::middle::ir_writer::IRWriter;

fn main() {
    let mut dir;
    let mut r2 = R2::new::<String>(None).expect("Unable to open r2");
    r2.init();
    let mut rmod = {
        let bin_info = r2.bin_info().expect("Failed to load bin_info");
        let fname = bin_info.core.unwrap().file.unwrap();
        let fname = Path::new(&fname).file_stem().unwrap();
        let fname = format!("{}_out", fname.to_str().unwrap());
        dir = PathBuf::from(".");
        dir.push(&fname);
        fs::create_dir_all(&dir).expect("Failed to create directory");
        println!("[*] Constructing ...");
        RadecoModule::from(&mut r2)
    };

    for (ref addr, ref mut rfn) in rmod.functions.iter_mut() {
        println!("[+] Analyzing: {} @ {:#x}", rfn.name, addr);
        {
            println!("  [*] Eliminating Dead Code");
            dce::collect(&mut rfn.ssa);
        }
        let mut ssa = {
            // Constant Propagation (sccp)
            println!("  [*] Propagating Constants");
            let mut analyzer = sccp::Analyzer::new(&mut rfn.ssa);
            analyzer.analyze();
            analyzer.emit_ssa()
        };
        {
            println!("  [*] Eliminating More DeadCode");
            dce::collect(&mut ssa);
        }
        rfn.ssa = ssa;
        {
            // Common SubExpression Elimination (cse)
            println!("  [*] Eliminating Common SubExpressions");
            let mut cse = CSE::new(&mut rfn.ssa);
            cse.run();
        }
        println!("  [*] Writing out IR");
        let mut fname = PathBuf::from(&dir);
        fname.push(&rfn.name);
        let mut ff = File::create(&fname).expect("Unable to create file");
        //println!("Local Variable info: {:?}", rfn.locals);
        let mut writer: IRWriter = Default::default();
        writer.emit_il(Some(rfn.name.clone()), &rfn.ssa, &mut ff);
        rmod.src.as_mut().unwrap().send(&format!("CC, {} @ {}", fname.to_str().unwrap(), addr));
    }

    rmod.src.as_mut().unwrap().send(&format!("e scr.color=true"))
}
<commit_msg>trivial write to single file #35<commit_after>#[macro_use] extern crate radeco_lib;
extern crate r2pipe;

use std::path::{Path, PathBuf};
use std::fs::{self, File};

use r2pipe::r2::R2;

use radeco_lib::frontend::containers::RadecoModule;
use radeco_lib::analysis::sccp::sccp;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::middle::{dce};
use radeco_lib::middle::ir_writer::IRWriter;

fn main() {
    let mut dir;
    let mut r2 = R2::new::<String>(None).expect("Unable to open r2");
    r2.init();
    let mut rmod = {
        let bin_info = r2.bin_info().expect("Failed to load bin_info");
        let fname = bin_info.core.unwrap().file.unwrap();
        let fname = Path::new(&fname).file_stem().unwrap();
        let fname = format!("{}_out", fname.to_str().unwrap());
        dir = PathBuf::from(".");
        dir.push(&fname);
        fs::create_dir_all(&dir).expect("Failed to create directory");
        println!("[*] Constructing ...");
        RadecoModule::from(&mut r2)
    };

    // Main file to contain IRs of all rfns
    let mut ffm;
    {
        let mut fname = PathBuf::from(&dir);
        fname.push("main");
        ffm = File::create(&fname).expect("Unable to create file");
    }

    for (ref addr, ref mut rfn) in rmod.functions.iter_mut() {
        println!("[+] Analyzing: {} @ {:#x}", rfn.name, addr);
        {
            println!("  [*] Eliminating Dead Code");
            dce::collect(&mut rfn.ssa);
        }
        let mut ssa = {
            // Constant Propagation (sccp)
            println!("  [*] Propagating Constants");
            let mut analyzer = sccp::Analyzer::new(&mut rfn.ssa);
            analyzer.analyze();
            analyzer.emit_ssa()
        };
        {
            println!("  [*] Eliminating More DeadCode");
            dce::collect(&mut ssa);
        }
        rfn.ssa = ssa;
        {
            // Common SubExpression Elimination (cse)
            println!("  [*] Eliminating Common SubExpressions");
            let mut cse = CSE::new(&mut rfn.ssa);
            cse.run();
        }
        println!("  [*] Writing out IR");
        let mut fname = PathBuf::from(&dir);
        fname.push(&rfn.name);
        let mut ff = File::create(&fname).expect("Unable to create file");
        //println!("Local Variable info: {:?}", rfn.locals);
        let mut writer: IRWriter = Default::default();
        writer.emit_il(Some(rfn.name.clone()), &rfn.ssa, &mut ff);
        writer.emit_il(Some(rfn.name.clone()), &rfn.ssa, &mut ffm);
        rmod.src.as_mut().unwrap().send(&format!("CC, {} @ {}", fname.to_str().unwrap(), addr));
    }

    rmod.src.as_mut().unwrap().send(&format!("e scr.color=true"))
}
<|endoftext|>