blob: 395a4417677dfb5a4e94d7d8569650bc714918af [file] [log] [blame]
Mohammed Naser9a6c35d2025-02-13 13:23:51 -05001use std::num::ParseIntError;
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum PasswdEntryError {
6 #[error("Failed to parse ID: {0}")]
7 FailedToParseID(#[from] ParseIntError),
8
9 #[error("Invalid passwd entry: {0}")]
10 InvalidPasswdEntry(String),
11}
12
13#[derive(Debug, Clone)]
14pub struct PasswdEntry {
15 pub name: String,
16 pub passwd: String,
17 pub uid: u32,
18 pub gid: u32,
19 pub gecos: String,
20 pub dir: String,
21 pub shell: String,
22}
23
24impl PasswdEntry {
25 pub fn from_line(line: &str) -> Result<PasswdEntry, PasswdEntryError> {
26 let parts: Vec<&str> = line.split(":").map(|part| part.trim()).collect();
27
28 if parts.len() != 7 {
29 return Err(PasswdEntryError::InvalidPasswdEntry(line.to_string()));
30 }
31
32 Ok(PasswdEntry {
33 name: parts[0].to_string(),
34 passwd: parts[1].to_string(),
35 uid: parts[2].parse()?,
36 gid: parts[3].parse()?,
37 gecos: parts[4].to_string(),
38 dir: parts[5].to_string(),
39 shell: parts[6].to_string(),
40 })
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn test_from_line_valid() {
50 let line = "username:x:1000:1000:User Name:/home/username:/bin/bash";
51 let entry = PasswdEntry::from_line(line).unwrap();
52 assert_eq!(entry.name, "username");
53 assert_eq!(entry.passwd, "x");
54 assert_eq!(entry.uid, 1000);
55 assert_eq!(entry.gid, 1000);
56 assert_eq!(entry.gecos, "User Name");
57 assert_eq!(entry.dir, "/home/username");
58 assert_eq!(entry.shell, "/bin/bash");
59 }
60
61 #[test]
62 fn test_from_line_invalid_uid() {
63 let line = "username:x:invalid:1000:User Name:/home/username:/bin/bash";
64 let result = PasswdEntry::from_line(line);
65 assert!(result.is_err());
66 }
67
68 #[test]
69 fn test_from_line_invalid_gid() {
70 let line = "username:x:1000:invalid:User Name:/home/username:/bin/bash";
71 let result = PasswdEntry::from_line(line);
72 assert!(result.is_err());
73 }
74
75 #[test]
76 fn test_from_line_missing_fields() {
77 let line = "username:x:1000:1000:User Name:/home/username";
78 let result = PasswdEntry::from_line(line);
79 assert!(result.is_err());
80 }
81}