extern crate chrono;
use chrono::prelude::DateTime;
use chrono::Utc;
use nt_time::FileTime;
use std::{fs, time::{
Duration,
UNIX_EPOCH
}, fmt::Display};
use std::os::windows::prelude::*;
use std::path::PathBuf;
pub struct MetadataPath {
path: PathBuf,
}
struct Props {
dir: bool,
file: bool,
read_only: bool,
hidden: bool,
system: bool,
reparse_file: bool
}
impl MetadataPath {
pub fn from(path: PathBuf) -> Self {
MetadataPath { path }
}
pub fn size(&self) -> u64 {
fs::metadata(self.path.clone()).unwrap().file_size()
}
pub fn props(&self) -> String {
let metadata = fs::metadata(self.path.clone()).unwrap();
let file_props = Self::props_string(metadata.file_attributes());
let last_write_time = Self::get_date(metadata.last_write_time());
format!("{} {}", file_props, last_write_time)
}
fn get_date(write_time: u64) -> String {
let write_time_seconds = write_time / 10_000_000 + 3600;
let windows_time = FileTime::NT_TIME_EPOCH + Duration::from_secs(write_time_seconds);
let unix_time = windows_time.to_unix_time();
let unix_time_with_epoch = UNIX_EPOCH + Duration::from_secs(unix_time.try_into().unwrap());
let datetime = DateTime::<Utc>::from(unix_time_with_epoch);
datetime.format("%Y-%m-%d %H:%M").to_string()
}
fn props_string(props: u32) -> String {
Props::new(props).to_string()
}
}
impl Props {
fn new(props: u32) -> Self {
let mut clone = props;
let mut props = props;
let mut read_only = false;
props >>= 1;
props <<= 1;
if props != clone {
read_only = true;
}
props >>= 1;
clone >>= 1;
let mut hidden = false;
props >>= 1;
props <<= 1;
if props != clone {
hidden = true;
}
props >>= 1;
clone >>= 1;
let mut system = false;
props >>= 1;
props <<= 1;
if props != clone {
system = true;
}
props >>= 2;
clone >>= 2;
let mut dir = false;
props >>= 1;
props <<= 1;
if props != clone {
dir = true;
}
props >>= 1;
clone >>= 1;
let mut file = false;
props >>= 1;
props <<= 1;
if props != clone && !dir {
file = true;
}
props >>= 5;
clone >>= 5;
let mut reparse_file = false;
props >>= 1;
props <<= 1;
if props != clone {
reparse_file = true;
}
Props { dir, file, read_only, hidden, system, reparse_file }
}
}
impl Display for Props {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}{}{}{}{}", if self.dir {'d'} else {'-'},
if self.file {'a'} else {'-'},
if self.read_only {'r'} else {'-'},
if self.hidden {'h'} else {'-'},
if self.system {'s'} else {'-'},
if self.reparse_file {'l'} else {'-'})
}
}