Read all tmpfiles.d entries in the target directory, and return a mapping from (file path) => (single tmpfiles.d entry line)
(rootfs: &Dir)
| 212 | /// Read all tmpfiles.d entries in the target directory, and return a mapping |
| 213 | /// from (file path) => (single tmpfiles.d entry line) |
| 214 | pub fn read_sysusers(rootfs: &Dir) -> Result<Vec<SysusersEntry>> { |
| 215 | let Some(d) = rootfs.open_dir_optional(SYSUSERSD)? else { |
| 216 | return Ok(Default::default()); |
| 217 | }; |
| 218 | let d = DirUtf8::from_cap_std(d); |
| 219 | let mut result = Vec::new(); |
| 220 | let mut found_users = BTreeSet::new(); |
| 221 | let mut found_groups = BTreeSet::new(); |
| 222 | for name in d.filenames_sorted()? { |
| 223 | let Some("conf") = Utf8Path::new(&name).extension() else { |
| 224 | continue; |
| 225 | }; |
| 226 | let r = d.open(&name).map(BufReader::new)?; |
| 227 | for line in r.lines() { |
| 228 | let line = line?; |
| 229 | if line.is_empty() || line.starts_with("#") { |
| 230 | continue; |
| 231 | } |
| 232 | let Some(e) = SysusersEntry::parse(&line).map_err(|e| Error::ParseFailureInFile { |
| 233 | path: name.clone().into(), |
| 234 | err: e.to_string(), |
| 235 | })? |
| 236 | else { |
| 237 | continue; |
| 238 | }; |
| 239 | match e { |
| 240 | SysusersEntry::User { |
| 241 | ref name, ref pgid, .. |
| 242 | } if !found_users.contains(name.as_str()) => { |
| 243 | found_users.insert(name.clone()); |
| 244 | found_groups.insert(name.clone()); |
| 245 | // Users implicitly create a group with the same name |
| 246 | let pgid = pgid.as_ref().and_then(|g| match g { |
| 247 | GroupReference::Numeric(n) => Some(IdSource::Numeric(*n)), |
| 248 | GroupReference::Path(p) => Some(IdSource::Path(p.clone())), |
| 249 | GroupReference::Name(_) => None, |
| 250 | }); |
| 251 | result.push(SysusersEntry::Group { |
| 252 | name: name.clone(), |
| 253 | id: pgid, |
| 254 | }); |
| 255 | result.push(e); |
| 256 | } |
| 257 | SysusersEntry::Group { ref name, .. } if !found_groups.contains(name.as_str()) => { |
| 258 | found_groups.insert(name.clone()); |
| 259 | result.push(e); |
| 260 | } |
| 261 | _ => { |
| 262 | // Ignore others. |
| 263 | } |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | Ok(result) |
| 268 | } |
| 269 | |
| 270 | /// The result of analyzing /etc/{passwd,group} in a root vs systemd-sysusers. |
| 271 | #[derive(Debug, Default)] |