summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2018-08-30 18:41:33 +0200
committerLinus Färnstrand <linus@mullvad.net>2018-08-30 18:41:33 +0200
commita7c3dc398dbd5cd8c86bec16e8ab96a5d7b21dd9 (patch)
tree25c3e1de42057d1d265aa48e6996dce4447539d7
parent74cf3950d47cadb91a982826b1acca3fc733b4fe (diff)
parent1e85c86bc6d289d9840507303501fe4d4ee9fe6a (diff)
downloadmullvadvpn-a7c3dc398dbd5cd8c86bec16e8ab96a5d7b21dd9.tar.xz
mullvadvpn-a7c3dc398dbd5cd8c86bec16e8ab96a5d7b21dd9.zip
Merge branch 'structure-problem-report-code'
-rw-r--r--mullvad-problem-report/src/main.rs131
-rw-r--r--mullvad-problem-report/src/metadata.rs126
2 files changed, 131 insertions, 126 deletions
diff --git a/mullvad-problem-report/src/main.rs b/mullvad-problem-report/src/main.rs
index de98bec2c1..b881c9d8d5 100644
--- a/mullvad-problem-report/src/main.rs
+++ b/mullvad-problem-report/src/main.rs
@@ -14,8 +14,6 @@ extern crate error_chain;
#[macro_use]
extern crate lazy_static;
extern crate regex;
-#[cfg(target_os = "linux")]
-extern crate rs_release;
extern crate uuid;
extern crate mullvad_paths;
@@ -31,7 +29,8 @@ use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::{self, BufWriter, Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
-use std::process::Command;
+
+mod metadata;
/// Maximum number of bytes to read from each log file
const LOG_MAX_READ_BYTES: usize = 128 * 1024;
@@ -87,7 +86,7 @@ quick_main!(run);
fn run() -> Result<()> {
let app = clap::App::new("problem-report")
- .version(product_version())
+ .version(metadata::PRODUCT_VERSION)
.author(crate_authors!())
.about("Mullvad VPN problem report tool. Collects logs and sends them to Mullvad support.")
.setting(clap::AppSettings::SubcommandRequired)
@@ -237,7 +236,7 @@ fn send_problem_report(user_email: &str, user_message: &str, report_path: &Path)
read_file_lossy(report_path, REPORT_MAX_SIZE)
.chain_err(|| ErrorKind::ReadLogError(report_path.to_path_buf()))?,
);
- let metadata = collect_metadata();
+ let metadata = metadata::collect();
let ca_path = mullvad_paths::resources::get_api_ca_path();
@@ -278,7 +277,7 @@ impl ProblemReport {
redact_custom_strings.retain(|redact| !redact.is_empty());
ProblemReport {
- metadata: collect_metadata(),
+ metadata: metadata::collect(),
logs: Vec::new(),
log_paths: HashSet::new(),
redact_custom_strings,
@@ -453,126 +452,6 @@ fn read_file_lossy(path: &Path, max_bytes: usize) -> io::Result<String> {
Ok(String::from_utf8_lossy(&buffer).into_owned())
}
-fn collect_metadata() -> HashMap<String, String> {
- let mut metadata = HashMap::new();
- metadata.insert("id".to_owned(), uuid::Uuid::new_v4().to_string());
- metadata.insert(
- "mullvad-product-version".to_owned(),
- product_version().to_owned(),
- );
- metadata.insert("os".to_owned(), os_version());
- metadata
-}
-
-fn product_version() -> &'static str {
- concat!(
- include_str!(concat!(env!("OUT_DIR"), "/product-version.txt")),
- " ",
- include_str!(concat!(env!("OUT_DIR"), "/git-commit-date.txt"))
- )
-}
-
-#[cfg(target_os = "linux")]
-fn os_version() -> String {
- // The OS version information is obtained first from the os-release file. If that information
- // is incomplete or unavailable, an attempt is made to obtain the version information from the
- // lsb_release command. If that fails, any partial information from os-release is used if
- // available, or a fallback message if reading from the os-release file produced no version
- // information.
- let os_version = read_os_release_file().unwrap_or_else(|incomplete_info| {
- parse_lsb_release().unwrap_or_else(|| {
- incomplete_info
- .unwrap_or_else(|| String::from("[failed to get Linux distribution/version]"))
- })
- });
-
- format!("Linux, {}", os_version)
-}
-
-#[cfg(target_os = "linux")]
-fn read_os_release_file() -> std::result::Result<String, Option<String>> {
- let mut os_release_info = rs_release::get_os_release().map_err(|_| None)?;
- let os_name = os_release_info.remove("NAME");
- let os_version = os_release_info.remove("VERSION");
-
- if os_name.is_some() || os_version.is_some() {
- let full_info_available = os_name.is_some() && os_version.is_some();
-
- let gathered_info = format!(
- "{} {}",
- os_name.unwrap_or_else(|| "[unknown distribution]".to_owned()),
- os_version.unwrap_or_else(|| "[unknown version]".to_owned())
- );
-
- if full_info_available {
- Ok(gathered_info)
- } else {
- // Partial version information
- Err(Some(gathered_info))
- }
- } else {
- // No information was obtained
- Err(None)
- }
-}
-
-#[cfg(target_os = "linux")]
-fn parse_lsb_release() -> Option<String> {
- command_stdout_lossy("lsb_release", &["-ds"]).and_then(|output| {
- if output.is_empty() {
- None
- } else {
- Some(output)
- }
- })
-}
-
-#[cfg(target_os = "macos")]
-fn os_version() -> String {
- format!(
- "macOS {}",
- command_stdout_lossy("sw_vers", &["-productVersion"])
- .unwrap_or(String::from("[Failed to detect version]"))
- )
-}
-
-#[cfg(windows)]
-fn os_version() -> String {
- let system_info =
- command_stdout_lossy("systeminfo", &["/FO", "LIST"]).unwrap_or_else(String::new);
-
- let mut os_name = None;
- let mut os_version = None;
-
- for info_line in system_info.lines() {
- let mut info_parts = info_line.split(":");
-
- match info_parts.next() {
- Some("OS Name") => os_name = info_parts.next(),
- Some("OS Version") => os_version = info_parts.next(),
- _ => {}
- }
- }
-
- match (os_name, os_version) {
- (None, None) => String::from("Windows [Failed to detect version]"),
- (Some(os_name), None) => os_name.trim().to_owned(),
- (None, Some(os_version)) => format!("Windows version {}", os_version.trim()),
- (Some(os_name), Some(os_version)) => {
- format!("{} version {}", os_name.trim(), os_version.trim())
- }
- }
-}
-
-/// Helper for getting stdout of some command as a String. Ignores the exit code of the command.
-fn command_stdout_lossy(cmd: &str, args: &[&str]) -> Option<String> {
- Command::new(cmd)
- .args(args)
- .output()
- .map(|output| String::from_utf8_lossy(&output.stdout).trim().to_string())
- .ok()
-}
-
#[cfg(not(windows))]
fn normalize_newlines(text: String) -> String {
text
diff --git a/mullvad-problem-report/src/metadata.rs b/mullvad-problem-report/src/metadata.rs
new file mode 100644
index 0000000000..d176d66c45
--- /dev/null
+++ b/mullvad-problem-report/src/metadata.rs
@@ -0,0 +1,126 @@
+use std::collections::HashMap;
+use std::process::Command;
+use uuid;
+
+pub const PRODUCT_VERSION: &str = concat!(
+ include_str!(concat!(env!("OUT_DIR"), "/product-version.txt")),
+ " ",
+ include_str!(concat!(env!("OUT_DIR"), "/git-commit-date.txt"))
+);
+
+pub fn collect() -> HashMap<String, String> {
+ let mut metadata = HashMap::new();
+ metadata.insert("id".to_owned(), uuid::Uuid::new_v4().to_string());
+ metadata.insert(
+ "mullvad-product-version".to_owned(),
+ PRODUCT_VERSION.to_owned(),
+ );
+ metadata.insert("os".to_owned(), os::version());
+ metadata
+}
+
+#[cfg(target_os = "linux")]
+mod os {
+ extern crate rs_release;
+
+ pub fn version() -> String {
+ // The OS version information is obtained first from the os-release file. If that
+ // information is incomplete or unavailable, an attempt is made to obtain the
+ // version information from the lsb_release command. If that fails, any partial
+ // information from os-release is used if available, or a fallback message if
+ // reading from the os-release file produced
+ // no version information.
+ let version = read_os_release_file().unwrap_or_else(|incomplete_info| {
+ parse_lsb_release().unwrap_or_else(|| {
+ incomplete_info.unwrap_or_else(|| String::from("[Failed to detect version]"))
+ })
+ });
+
+ format!("Linux {}", version)
+ }
+
+ fn read_os_release_file() -> Result<String, Option<String>> {
+ let mut os_release_info = rs_release::get_os_release().map_err(|_| None)?;
+ let os_name = os_release_info.remove("NAME");
+ let os_version = os_release_info.remove("VERSION");
+
+ if os_name.is_some() || os_version.is_some() {
+ let full_info_available = os_name.is_some() && os_version.is_some();
+
+ let gathered_info = format!(
+ "{} {}",
+ os_name.unwrap_or_else(|| "[unknown distribution]".to_owned()),
+ os_version.unwrap_or_else(|| "[unknown version]".to_owned())
+ );
+
+ if full_info_available {
+ Ok(gathered_info)
+ } else {
+ // Partial version information
+ Err(Some(gathered_info))
+ }
+ } else {
+ // No information was obtained
+ Err(None)
+ }
+ }
+
+ fn parse_lsb_release() -> Option<String> {
+ super::command_stdout_lossy("lsb_release", &["-ds"]).and_then(|output| {
+ if output.is_empty() {
+ None
+ } else {
+ Some(output)
+ }
+ })
+ }
+}
+
+#[cfg(target_os = "macos")]
+mod os {
+ pub fn version() -> String {
+ format!(
+ "macOS {}",
+ super::command_stdout_lossy("sw_vers", &["-productVersion"])
+ .unwrap_or(String::from("[Failed to detect version]"))
+ )
+ }
+}
+
+#[cfg(windows)]
+mod os {
+ pub fn version() -> String {
+ let system_info =
+ super::command_stdout_lossy("systeminfo", &["/FO", "LIST"]).unwrap_or_else(String::new);
+
+ let mut version = None;
+ let mut full_version = None;
+
+ for info_line in system_info.lines() {
+ let mut info_parts = info_line.split(":");
+
+ match info_parts.next() {
+ Some("OS Name") => {
+ version = info_parts
+ .next()
+ .map(|s| s.trim().trim_left_matches("Microsoft Windows "))
+ }
+ Some("OS Version") => full_version = info_parts.next().map(str::trim),
+ _ => {}
+ }
+ }
+
+ let version = version.unwrap_or("N/A");
+ let full_version = full_version.unwrap_or("N/A");
+ format!("Windows {} ({})", version, full_version)
+ }
+}
+
+/// Helper for getting stdout of some command as a String. Ignores the exit code of the command.
+fn command_stdout_lossy(cmd: &str, args: &[&str]) -> Option<String> {
+ Command::new(cmd)
+ .args(args)
+ .output()
+ .map(|output| String::from_utf8_lossy(&output.stdout).trim().to_string())
+ .ok()
+}