blob: 395a4417677dfb5a4e94d7d8569650bc714918af [file] [log] [blame]
use std::num::ParseIntError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum PasswdEntryError {
#[error("Failed to parse ID: {0}")]
FailedToParseID(#[from] ParseIntError),
#[error("Invalid passwd entry: {0}")]
InvalidPasswdEntry(String),
}
#[derive(Debug, Clone)]
pub struct PasswdEntry {
pub name: String,
pub passwd: String,
pub uid: u32,
pub gid: u32,
pub gecos: String,
pub dir: String,
pub shell: String,
}
impl PasswdEntry {
pub fn from_line(line: &str) -> Result<PasswdEntry, PasswdEntryError> {
let parts: Vec<&str> = line.split(":").map(|part| part.trim()).collect();
if parts.len() != 7 {
return Err(PasswdEntryError::InvalidPasswdEntry(line.to_string()));
}
Ok(PasswdEntry {
name: parts[0].to_string(),
passwd: parts[1].to_string(),
uid: parts[2].parse()?,
gid: parts[3].parse()?,
gecos: parts[4].to_string(),
dir: parts[5].to_string(),
shell: parts[6].to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_line_valid() {
let line = "username:x:1000:1000:User Name:/home/username:/bin/bash";
let entry = PasswdEntry::from_line(line).unwrap();
assert_eq!(entry.name, "username");
assert_eq!(entry.passwd, "x");
assert_eq!(entry.uid, 1000);
assert_eq!(entry.gid, 1000);
assert_eq!(entry.gecos, "User Name");
assert_eq!(entry.dir, "/home/username");
assert_eq!(entry.shell, "/bin/bash");
}
#[test]
fn test_from_line_invalid_uid() {
let line = "username:x:invalid:1000:User Name:/home/username:/bin/bash";
let result = PasswdEntry::from_line(line);
assert!(result.is_err());
}
#[test]
fn test_from_line_invalid_gid() {
let line = "username:x:1000:invalid:User Name:/home/username:/bin/bash";
let result = PasswdEntry::from_line(line);
assert!(result.is_err());
}
#[test]
fn test_from_line_missing_fields() {
let line = "username:x:1000:1000:User Name:/home/username";
let result = PasswdEntry::from_line(line);
assert!(result.is_err());
}
}