From 42295905416be2ea199c0dcc40026da639d3293d Mon Sep 17 00:00:00 2001 From: Jonathon Reinhart Date: Sun, 31 Dec 2023 11:51:26 -0500 Subject: [PATCH] scubainit: Avoid lifetimes on EntFile{Reader,Writer} Rather than use lifetimes on the EntFileReader and EntFileWriter structs, we can implement the common into_inner() convention. This consumes the outer object returning the inner wrapped object, which in this case is the File which we want to reuse. This matches e.g. `std::io::BufReader::into_inner()`. Note that this also requires changing the way the reader is iterated: We use `for x in &mut reader` which avoids moving the `reader` object into the loop, allowing `into_inner()` to be subsequently called. See the discussion here: https://github.com/JonathonReinhart/scuba/pull/239#issuecomment-1872970751. --- scubainit/src/entfiles.rs | 25 ++++++++++++++++--------- scubainit/src/groups.rs | 4 ++-- scubainit/src/main.rs | 24 +++++++++++++++--------- scubainit/src/passwd.rs | 4 ++-- scubainit/src/shadow.rs | 4 ++-- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/scubainit/src/entfiles.rs b/scubainit/src/entfiles.rs index 786b2df..60a1b6a 100644 --- a/scubainit/src/entfiles.rs +++ b/scubainit/src/entfiles.rs @@ -86,21 +86,28 @@ impl<'a> EntLineParser<'a> { //////////////////////////////////////////////////////////////////////////////// // EntFileReader -pub struct EntFileReader<'a, T> { - reader: BufReader<&'a File>, +pub struct EntFileReader { + reader: BufReader, marker: PhantomData, // T must be used } -impl EntFileReader<'_, T> { - pub fn new(file: &File) -> EntFileReader { +impl EntFileReader { + pub fn new(file: File) -> EntFileReader { EntFileReader { reader: BufReader::new(file), marker: PhantomData, } } + + /// Unwraps this `EntFileReader`, returning the underlying File. + /// + /// Note that the position of the File is undefined. + pub fn into_inner(self) -> File { + self.reader.into_inner() + } } -impl Iterator for EntFileReader<'_, T> { +impl Iterator for EntFileReader { type Item = Result; fn next(&mut self) -> Option { @@ -130,13 +137,13 @@ impl Iterator for EntFileReader<'_, T> { //////////////////////////////////////////////////////////////////////////////// // EntFileWriter -pub struct EntFileWriter<'a, T> { - file: &'a File, +pub struct EntFileWriter { + file: File, marker: PhantomData, // T must be used } -impl EntFileWriter<'_, T> { - pub fn new(file: &File) -> EntFileWriter { +impl EntFileWriter { + pub fn new(file: File) -> EntFileWriter { EntFileWriter { file: file, marker: PhantomData, diff --git a/scubainit/src/groups.rs b/scubainit/src/groups.rs index f1ac31d..2ee5a1e 100644 --- a/scubainit/src/groups.rs +++ b/scubainit/src/groups.rs @@ -9,8 +9,8 @@ pub struct GroupEntry { pub members: Vec, } -pub type GroupFileReader<'a> = EntFileReader<'a, GroupEntry>; -pub type GroupFileWriter<'a> = EntFileWriter<'a, GroupEntry>; +pub type GroupFileReader = EntFileReader; +pub type GroupFileWriter = EntFileWriter; impl Entry for GroupEntry { fn from_line(line: &str) -> Result { diff --git a/scubainit/src/main.rs b/scubainit/src/main.rs index f57f9d7..360666d 100644 --- a/scubainit/src/main.rs +++ b/scubainit/src/main.rs @@ -112,8 +112,8 @@ impl UserInfo { let file = open_read_append(ETC_GROUP)?; // Try to find a conflicting group (one matching name or gid). - let reader = groups::GroupFileReader::new(&file); - for grp in reader { + let mut reader = groups::GroupFileReader::new(file); + for grp in &mut reader { let grp = grp?; let name_matches = grp.name.as_str() == group_name; let gid_matches = grp.gid == gid; @@ -131,6 +131,8 @@ impl UserInfo { } } + let file = reader.into_inner(); + // Okay, add group let grp = groups::GroupEntry { name: group_name.to_owned(), @@ -138,7 +140,7 @@ impl UserInfo { gid, members: Vec::new(), }; - let mut writer = groups::GroupFileWriter::new(&file); + let mut writer = groups::GroupFileWriter::new(file); Ok(writer.write(&grp)?) } @@ -150,8 +152,8 @@ impl UserInfo { let file = open_read_append(ETC_PASSWD)?; // Try to find a conflicting user (one matching name or uid). - let reader = passwd::PasswdFileReader::new(&file); - for pwd in reader { + let mut reader = passwd::PasswdFileReader::new(file); + for pwd in &mut reader { let pwd = pwd?; let name_matches = pwd.name.as_str() == user_name; let uid_matches = pwd.uid == uid; @@ -169,6 +171,8 @@ impl UserInfo { } } + let file = reader.into_inner(); + // Okay, add user let home_dir_path = self.home_dir(); let home_dir_str = home_dir_path.to_str().context("Invalid home_dir")?; @@ -181,7 +185,7 @@ impl UserInfo { home_dir: home_dir_str.to_owned(), shell: DEFAULT_SHELL.to_owned(), }; - let mut writer = passwd::PasswdFileWriter::new(&file); + let mut writer = passwd::PasswdFileWriter::new(file); Ok(writer.write(&user)?) } @@ -192,8 +196,8 @@ impl UserInfo { let file = open_read_append(ETC_SHADOW)?; // Try to find a conflicting user (one matching name). - let reader = shadow::ShadowFileReader::new(&file); - for sp in reader { + let mut reader = shadow::ShadowFileReader::new(file); + for sp in &mut reader { let sp = sp?; if sp.name.as_str() == user_name { // Already exists; we don't really care about its values @@ -201,6 +205,8 @@ impl UserInfo { } } + let file = reader.into_inner(); + // Okay, add shadow entry let entry = shadow::ShadowEntry { name: user_name.to_owned(), @@ -212,7 +218,7 @@ impl UserInfo { inact_period: None, expire_date: None, }; - let mut writer = shadow::ShadowFileWriter::new(&file); + let mut writer = shadow::ShadowFileWriter::new(file); Ok(writer.write(&entry)?) } diff --git a/scubainit/src/passwd.rs b/scubainit/src/passwd.rs index 32e6392..9ed52b9 100644 --- a/scubainit/src/passwd.rs +++ b/scubainit/src/passwd.rs @@ -11,8 +11,8 @@ pub struct PasswdEntry { pub shell: String, // TODO: Option } -pub type PasswdFileReader<'a> = EntFileReader<'a, PasswdEntry>; -pub type PasswdFileWriter<'a> = EntFileWriter<'a, PasswdEntry>; +pub type PasswdFileReader = EntFileReader; +pub type PasswdFileWriter = EntFileWriter; impl Entry for PasswdEntry { fn from_line(line: &str) -> Result { diff --git a/scubainit/src/shadow.rs b/scubainit/src/shadow.rs index bc5792c..7a45ab0 100644 --- a/scubainit/src/shadow.rs +++ b/scubainit/src/shadow.rs @@ -14,8 +14,8 @@ pub struct ShadowEntry { // reserved } -pub type ShadowFileReader<'a> = EntFileReader<'a, ShadowEntry>; -pub type ShadowFileWriter<'a> = EntFileWriter<'a, ShadowEntry>; +pub type ShadowFileReader = EntFileReader; +pub type ShadowFileWriter = EntFileWriter; impl Entry for ShadowEntry { fn from_line(line: &str) -> Result {