From a645ebac75d304759a2264690861932ea50018e5 Mon Sep 17 00:00:00 2001 From: Dietrich Date: Wed, 7 Oct 2020 09:30:59 +0200 Subject: [PATCH] lifetime error --- src/bin/read_all.rs | 1 - src/group/mod.rs | 5 +-- src/user/mod.rs | 11 ++++-- src/user/shadow_fields.rs | 5 +-- src/userlib.rs | 72 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/bin/read_all.rs b/src/bin/read_all.rs index 27056b1..7cc05ca 100644 --- a/src/bin/read_all.rs +++ b/src/bin/read_all.rs @@ -17,7 +17,6 @@ fn main() { for line in reader.lines() { let line = line.unwrap(); - println!("{}", line); println!("{}", User::new_from_string(&line).unwrap()); } diff --git a/src/group/mod.rs b/src/group/mod.rs index 351b7ec..963c0bf 100644 --- a/src/group/mod.rs +++ b/src/group/mod.rs @@ -7,6 +7,7 @@ )] #![allow(clippy::non_ascii_literal)] +use crate::userlib::NewFromString; use log::warn; use regex::Regex; @@ -84,7 +85,7 @@ impl<'a> Display for Group<'a> { } } -impl<'a> Group<'a> { +impl<'a> NewFromString<'a> for Group<'a> { /// Parse a line formatted like one in `/etc/shadow` and construct a matching `Shadow` instance /// /// # Example @@ -97,7 +98,7 @@ impl<'a> Group<'a> { /// /// # Errors /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed. - pub fn new_from_string(line: &'a str) -> Result { + fn new_from_string(line: &'a str) -> Result { println!("{}", &line); let elements: Vec<&str> = line.split(':').collect(); if elements.len() == 4 { diff --git a/src/user/mod.rs b/src/user/mod.rs index a91bbbb..cde6916 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -2,6 +2,7 @@ pub mod gecos_fields; pub mod passwd_fields; pub mod shadow_fields; +use crate::userlib::NewFromString; use std::convert::TryFrom; use std::fmt::{self, Display}; @@ -18,7 +19,7 @@ pub struct User<'a> { shell_path: crate::ShellPath<'a>, /* Shell program. */ } -impl<'a> User<'a> { +impl<'a> NewFromString<'a> for User<'a> { /// Parse a line formatted like one in `/etc/passwd` and construct a matching [`adduser::User`] instance /// /// # Example @@ -31,7 +32,10 @@ impl<'a> User<'a> { /// /// # Errors /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed. - pub fn new_from_string(line: &'a str) -> Result { + fn new_from_string(line: &'a str) -> Result + where + Self: Sized, + { let elements: Vec<&str> = line.split(':').collect(); if elements.len() == 7 { Ok(Self { @@ -50,6 +54,9 @@ impl<'a> User<'a> { Err("Failed to parse: not enough elements".into()) } } +} + +impl<'a> User<'a> { #[must_use] pub const fn get_username(&self) -> &'a str { self.username.username diff --git a/src/user/shadow_fields.rs b/src/user/shadow_fields.rs index 12943e1..ec53357 100644 --- a/src/user/shadow_fields.rs +++ b/src/user/shadow_fields.rs @@ -7,6 +7,7 @@ )] #![allow(clippy::non_ascii_literal)] +use crate::userlib::NewFromString; use log::warn; use crate::userlib_error::UserLibError; @@ -77,7 +78,7 @@ fn show_option_duration(input: Option) -> String { } } -impl<'a> Shadow<'a> { +impl<'a> NewFromString<'a> for Shadow<'a> { /// Parse a line formatted like one in `/etc/shadow` and construct a matching `Shadow` instance /// /// # Example @@ -90,7 +91,7 @@ impl<'a> Shadow<'a> { /// /// # Errors /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed. - pub fn new_from_string(line: &'a str) -> Result { + fn new_from_string(line: &'a str) -> Result { println!("{}", &line); let elements: Vec<&str> = line.split(':').collect(); if elements.len() == 9 { diff --git a/src/userlib.rs b/src/userlib.rs index 18340b8..a15b06d 100644 --- a/src/userlib.rs +++ b/src/userlib.rs @@ -8,13 +8,33 @@ #![allow(clippy::non_ascii_literal)] use log::warn; +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::PathBuf; pub struct UserDBLocal<'a> { + source_files: Files, pub passwd_entries: Vec>, pub shadow_entries: Vec>, pub group_entries: Vec>, } +pub struct Files { + passwd: Option, + shadow: Option, + group: Option, +} + +impl Default for Files { + fn default() -> Self { + Self { + passwd: Some(PathBuf::from("/etc/passwd")), + shadow: Some(PathBuf::from("/etc/shadow")), + group: Some(PathBuf::from("/etc/group")), + } + } +} + impl<'a> UserDBLocal<'a> { #[must_use] pub fn import_from_strings( @@ -23,6 +43,11 @@ impl<'a> UserDBLocal<'a> { group_content: &'a str, ) -> Self { let res = UserDBLocal { + source_files: Files { + passwd: None, + group: None, + shadow: None, + }, passwd_entries: passwd_content .lines() .filter_map(|line| { @@ -57,6 +82,53 @@ impl<'a> UserDBLocal<'a> { }; res } + + pub fn load_files(files: Files) -> Self { + let passwd_file = + File::open(files.group.expect("passwd file path cannot be None")).unwrap(); + let mut passwd_reader = BufReader::new(passwd_file); + let mut my_passwd_lines = String::new(); + passwd_reader.read_to_string(&mut my_passwd_lines).unwrap(); + let group_file = File::open(files.group.expect("group file path cannot be None")).unwrap(); + let mut group_reader = BufReader::new(group_file); + let mut my_group_lines = String::new(); + group_reader.read_to_string(&mut my_group_lines).unwrap(); + let shadow_file = File::open(files.shadow.expect("shadow file path cannot be None")) + .expect("Failed to read the shadow file. Most of the time root permissions are needed"); + let mut shadow_reader = BufReader::new(group_file); + let mut my_shadow_lines = String::new(); + shadow_reader.read_to_string(&mut my_shadow_lines).unwrap(); + + Self { + source_files: files, + passwd_entries: string_to(&my_passwd_lines), + group_entries: string_to(&my_group_lines), + shadow_entries: string_to(&my_shadow_lines), + } + } +} + +pub trait NewFromString<'a> { + fn new_from_string(line: &'a str) -> Result + where + Self: Sized; +} + +fn string_to<'a, T>(source: &'a str) -> Vec +where + T: NewFromString<'a>, +{ + source + .lines() + .filter_map(|line| { + if line.len() > 5 { + println!("{}", line); + Some(T::new_from_string(line).expect("failed to read lines")) + } else { + None + } + }) + .collect() } #[test]