lx_cli/
reader.rs

1/// Handles directory traversal and gathering file metadata.
2use crate::file_entry::FileEntry;
3use std::fs;
4use std::io;
5use std::os::unix::fs::{MetadataExt, PermissionsExt};
6use std::path::Path;
7
8pub fn read_directory(target_path: &Path, show_hidden: bool) -> io::Result<Vec<FileEntry>> {
9    let mut entries: Vec<FileEntry> = Vec::new();
10
11    for entry in fs::read_dir(target_path)? {
12        let entry = entry?;
13        let path = entry.path();
14
15        // Skip hidden files unless show_hidden is true
16        if !show_hidden {
17            if let Some(filename) = path.file_name() {
18                if let Some(name) = filename.to_str() {
19                    if name.starts_with('.') {
20                        continue;
21                    }
22                }
23            }
24        }
25
26        let metadata = entry.metadata()?;
27        let is_dir = metadata.is_dir();
28        let is_executable = !is_dir && (metadata.permissions().mode() & 0o111) != 0;
29
30        // Get owner name
31        let uid = metadata.uid();
32        let owner = get_username(uid);
33
34        // Get group name
35        let gid = metadata.gid();
36        let group = get_groupname(gid);
37
38        // Get number of hard links
39        let nlink = metadata.nlink();
40
41        // Get modification time
42        let modified = metadata
43            .modified()
44            .unwrap_or(std::time::SystemTime::UNIX_EPOCH);
45
46        // Get size
47        let size = metadata.len();
48
49        entries.push(FileEntry {
50            path,
51            is_dir,
52            is_executable,
53            mode: metadata.permissions().mode(),
54            size,
55            modified,
56            owner,
57            group,
58            nlink,
59        });
60    }
61
62    Ok(entries)
63}
64
65fn get_username(uid: u32) -> String {
66    // Try to get username from system, fallback to uid
67    #[cfg(unix)]
68    {
69        use std::ffi::CStr;
70        unsafe {
71            let passwd = libc::getpwuid(uid);
72            if !passwd.is_null() {
73                let name = CStr::from_ptr((*passwd).pw_name);
74                if let Ok(name_str) = name.to_str() {
75                    return name_str.to_string();
76                }
77            }
78        }
79    }
80    uid.to_string()
81}
82
83fn get_groupname(gid: u32) -> String {
84    // Try to get group name from system, fallback to gid
85    #[cfg(unix)]
86    {
87        use std::ffi::CStr;
88        unsafe {
89            let group = libc::getgrgid(gid);
90            if !group.is_null() {
91                let name = CStr::from_ptr((*group).gr_name);
92                if let Ok(name_str) = name.to_str() {
93                    return name_str.to_string();
94                }
95            }
96        }
97    }
98    gid.to_string()
99}