提交 b5a1b24b 编写于 作者: B Ben S

Cache user and group names

I checked strace and it was reading /etc/passwd every time it needed to
look up a user or group. Now it only does it once per.
上级 5c0d2d07
......@@ -7,6 +7,7 @@ use std::os;
use file::File;
use dir::Dir;
use options::Options;
use unix::Unix;
pub mod colours;
pub mod column;
......@@ -61,8 +62,10 @@ fn exa(options: &Options, string: String) {
// width of each column based on the length of the results and
// padding the fields during output.
let mut cache = Unix::empty_cache();
let table: Vec<Vec<String>> = files.iter()
.map(|f| options.columns.iter().map(|c| f.display(c)).collect())
.map(|f| options.columns.iter().map(|c| f.display(c, &mut cache)).collect())
.collect();
// Each column needs to have its invisible colour-formatting
......
......@@ -4,7 +4,7 @@ use std::io;
use column::{Column, Permissions, FileName, FileSize, User, Group};
use format::{format_metric_bytes, format_IEC_bytes};
use unix::{get_user_name, get_group_name};
use unix::Unix;
use sort::SortPart;
use dir::Dir;
use filetype::HasType;
......@@ -89,7 +89,7 @@ impl<'a> File<'a> {
}
}
pub fn display(&self, column: &Column) -> String {
pub fn display(&self, column: &Column, unix: &mut Unix) -> String {
match *column {
Permissions => self.permissions_string(),
FileName => self.file_name(),
......@@ -99,10 +99,10 @@ impl<'a> File<'a> {
// usually means it was deleted but its files weren't.
User(uid) => {
let style = if uid == self.stat.unstable.uid { Yellow.bold() } else { Plain };
let string = get_user_name(self.stat.unstable.uid as i32).unwrap_or(self.stat.unstable.uid.to_str());
let string = unix.get_user_name(self.stat.unstable.uid as i32).unwrap_or(self.stat.unstable.uid.to_str());
return style.paint(string.as_slice());
},
Group => get_group_name(self.stat.unstable.gid as u32).unwrap_or(self.stat.unstable.gid.to_str()),
Group => unix.get_group_name(self.stat.unstable.gid as u32).unwrap_or(self.stat.unstable.gid.to_str()),
}
}
......
use std::str::raw::from_c_str;
use std::ptr::read;
use std::collections::hashmap::HashMap;
mod c {
#![allow(non_camel_case_types)]
......@@ -34,24 +35,41 @@ mod c {
pub fn getuid() -> libc::c_int;
}
}
pub struct Unix {
user_names: HashMap<i32, Option<String>>,
group_names: HashMap<u32, Option<String>>,
}
pub fn get_user_name(uid: i32) -> Option<String> {
let pw = unsafe { c::getpwuid(uid) };
if pw.is_not_null() {
return unsafe { Some(from_c_str(read(pw).pw_name)) };
}
else {
return None;
impl Unix {
pub fn empty_cache() -> Unix {
Unix {
user_names: HashMap::new(),
group_names: HashMap::new(),
}
}
}
pub fn get_group_name(gid: u32) -> Option<String> {
let gr = unsafe { c::getgrgid(gid) };
if gr.is_not_null() {
return unsafe { Some(from_c_str(read(gr).gr_name)) };
pub fn get_user_name<'a> (&'a mut self, uid: i32) -> Option<String> {
self.user_names.find_or_insert_with(uid, |&u| {
let pw = unsafe { c::getpwuid(u) };
if pw.is_not_null() {
return unsafe { Some(from_c_str(read(pw).pw_name)) };
}
else {
return None;
}
}).clone()
}
else {
return None;
pub fn get_group_name<'a>(&'a mut self, gid: u32) -> Option<String> {
self.group_names.find_or_insert_with(gid, |&gid| {
let gr = unsafe { c::getgrgid(gid) };
if gr.is_not_null() {
return unsafe { Some(from_c_str(read(gr).gr_name)) };
}
else {
return None;
}
}).clone()
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册