Просмотр исходного кода

Add user and group columns

This meant writing some libc interaction, which wasn't actually too bad.
Ben S 11 лет назад
Родитель
Сommit
d76fee7328
4 измененных файлов с 64 добавлено и 1 удалено
  1. 4 0
      column.rs
  2. 1 0
      exa.rs
  3. 4 1
      file.rs
  4. 55 0
      unix.rs

+ 4 - 0
column.rs

@@ -2,12 +2,16 @@ pub enum Column {
     Permissions,
     Permissions,
     FileName,
     FileName,
     FileSize(bool),
     FileSize(bool),
+    User,
+    Group,
 }
 }
 
 
 pub fn defaultColumns() -> ~[Column] {
 pub fn defaultColumns() -> ~[Column] {
     return ~[
     return ~[
         Permissions,
         Permissions,
         FileSize(false),
         FileSize(false),
+        User,
+        Group,
         FileName,
         FileName,
     ];
     ];
 }
 }

+ 1 - 0
exa.rs

@@ -9,6 +9,7 @@ pub mod colours;
 pub mod column;
 pub mod column;
 pub mod format;
 pub mod format;
 pub mod file;
 pub mod file;
+pub mod unix;
 
 
 struct Options {
 struct Options {
     showInvisibles: bool,
     showInvisibles: bool,

+ 4 - 1
file.rs

@@ -2,8 +2,9 @@ use std::io::fs;
 use std::io;
 use std::io;
 
 
 use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan};
 use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan};
-use column::{Column, Permissions, FileName, FileSize};
+use column::{Column, Permissions, FileName, FileSize, User, Group};
 use format::{formatBinaryBytes, formatDecimalBytes};
 use format::{formatBinaryBytes, formatDecimalBytes};
+use unix::{get_user_name, get_group_name};
 
 
 // Each file is definitely going to get `stat`ted at least once, if
 // Each file is definitely going to get `stat`ted at least once, if
 // only to determine what kind of file it is, so carry the `stat`
 // only to determine what kind of file it is, so carry the `stat`
@@ -39,6 +40,8 @@ impl<'a> File<'a> {
             Permissions => self.permissions(),
             Permissions => self.permissions(),
             FileName => self.file_colour().paint(self.name.to_owned()),
             FileName => self.file_colour().paint(self.name.to_owned()),
             FileSize(si) => self.file_size(si),
             FileSize(si) => self.file_size(si),
+            User => get_user_name(self.stat.unstable.uid as i32).expect("???"),
+            Group => get_group_name(self.stat.unstable.gid as u32).expect("???"),
         }
         }
     }
     }
 
 

+ 55 - 0
unix.rs

@@ -0,0 +1,55 @@
+use std::str::raw::from_c_str;
+use std::ptr::read;
+
+mod c {
+    #![allow(non_camel_case_types)]
+    extern crate libc;
+    use self::libc::{
+        c_char,
+        c_int,
+        uid_t,
+        time_t
+    };
+
+    pub struct c_passwd {
+        pub pw_name:    *c_char,  // login name
+        pub pw_passwd:  *c_char,
+        pub pw_uid:     c_int,    // user ID
+        pub pw_gid:     c_int,    // group ID
+        pub pw_change:  time_t,
+        pub pw_class:   *c_char,
+        pub pw_gecos:   *c_char,  // full name
+        pub pw_dir:     *c_char,  // login dir
+        pub pw_shell:   *c_char,  // login shell
+        pub pw_expire:  time_t    // password expiry time
+    }
+
+    pub struct c_group {
+        pub gr_name: *c_char      // group name
+    }
+
+    extern {
+        pub fn getpwuid(uid: c_int) -> *c_passwd;
+        pub fn getgrgid(gid: uid_t) -> *c_group;
+    }
+}
+
+pub fn get_user_name(uid: i32) -> Option<~str> {
+    let pw = unsafe { c::getpwuid(uid) };
+    if pw.is_not_null() {
+        return unsafe { Some(from_c_str(read(pw).pw_name)) };
+    }
+    else {
+        return None;
+    }
+}
+
+pub fn get_group_name(gid: u32) -> Option<~str> {
+    let gr = unsafe { c::getgrgid(gid) };
+    if gr.is_not_null() {
+        return unsafe { Some(from_c_str(read(gr).gr_name)) };
+    }
+    else {
+        return None;
+    }
+}