Mohammed Naser | 942099f | 2025-02-13 13:23:51 -0500 | [diff] [blame] | 1 | use std::num::ParseIntError; |
| 2 | use thiserror::Error; |
| 3 | |
| 4 | #[derive(Debug, Error)] |
| 5 | pub 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)] |
| 14 | pub 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 | |
| 24 | impl 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)] |
| 45 | mod 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 | } |