extern crate users; extern crate hex; use std::io; use std::fs; use std::os::unix::fs::PermissionsExt; use std::os::linux::fs::MetadataExt; use std::path::Path; use std::io::prelude::*; use walkdir::DirEntry; use chrono::prelude::DateTime; use chrono::{Utc}; use crypto_hash::{Algorithm, Hasher}; use serde_yaml; fn str_value(s: &str) -> serde_yaml::Value { serde_yaml::to_value(s).unwrap() } fn int_value(i: u64) -> serde_yaml::Value { serde_yaml::to_value(i).unwrap() } pub fn name(e: &DirEntry) -> serde_yaml::Value { str_value(&e.path().to_string_lossy()) } pub fn mtime(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); let mtime = meta.modified().unwrap(); let datetime = DateTime::::from(mtime); let mtime = datetime.format("%Y-%m-%d %H:%M:%S.%f %z").to_string(); str_value(&mtime) } pub fn mode(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); str_value(&format!("{:o}", meta.permissions().mode())) } pub fn inode(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.st_ino()) } pub fn dev(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.st_dev()) } pub fn nlink(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.st_nlink()) } pub fn size(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.len()) } pub fn uid(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.st_uid() as u64) } pub fn gid(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); int_value(meta.st_gid() as u64) } pub fn username(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); if let Some(u) = users::get_user_by_uid(meta.st_uid()) { str_value(u.name()) } else { str_value("unknown user") } } pub fn group(e: &DirEntry) -> serde_yaml::Value { let meta = e.metadata().unwrap(); if let Some(g) = users::get_group_by_gid(meta.st_gid()) { str_value(g.name()) } else { str_value("unknown group") } } pub fn sha256(e: &DirEntry) -> serde_yaml::Value { if let Ok(digest) = sha256_file(e.path()) { str_value(&digest) } else { str_value("error reading file") } } fn sha256_file(filename: &Path) -> io::Result { let file = fs::File::open(filename)?; let mut reader = io::BufReader::new(file); let mut hasher = Hasher::new(Algorithm::SHA256); let mut buf = [0; 1024 * 1024]; let mut done = false; while !done { let n = reader.read(&mut buf)?; if n == 0 { done = true; } else { hasher.write(&buf[0..n])?; } } let digest = hasher.finish(); Ok(hex::encode(digest)) }