#[cfg(windows)]
extern crate winapi;
use std::ffi::CString;
use std::path::Path;
bitflags! {
pub struct Attributes: u32 {
const NORMAL = 128;
const HIDDEN = 2;
const READ_ONLY = 1;
}
}
const ATTRIBUTES: [Attributes; 3] = [Attributes::NORMAL, Attributes::HIDDEN, Attributes::READ_ONLY];
#[cfg(windows)]
pub fn set_attribute(file: &Path, attrib: Attributes) -> bool {
use self::winapi::um::fileapi::SetFileAttributesA;
unsafe {
let file_string: CString = CString::new(file.to_str().unwrap()).unwrap();
let success = SetFileAttributesA(file_string.as_ptr(), attrib.bits);
return success != 0;
}
}
#[cfg(windows)]
pub fn has_attribute(file: &Path, attrib: Attributes) -> bool {
use self::winapi::um::fileapi::GetFileAttributesA;
use self::winapi::um::fileapi::INVALID_FILE_ATTRIBUTES;
unsafe {
let file_string: CString = CString::new(file.to_str().unwrap()).unwrap();
let bits = GetFileAttributesA(file_string.as_ptr());
if bits == INVALID_FILE_ATTRIBUTES {
return false;
}
return bits & attrib.bits == attrib.bits;
}
}
#[cfg(windows)]
pub fn get_attributes(file: &Path) -> Result<Vec<Attributes>, String> {
use self::winapi::um::fileapi::GetFileAttributesA;
use self::winapi::um::fileapi::INVALID_FILE_ATTRIBUTES;
let mut output: Vec<Attributes> = Vec::new();
unsafe {
let file_string: CString = CString::new(file.to_str().unwrap()).unwrap();
let bits = GetFileAttributesA(file_string.as_ptr());
if bits == INVALID_FILE_ATTRIBUTES {
return Err(String::from("Windows.h Error: Invalid file attributes. Use obtain_errors() for a detailed error."));
}
for att in ATTRIBUTES.iter() {
if bits & att.bits == att.bits {
output.push(*att);
}
}
return Ok(output);
}
}
#[cfg(unix)]
pub fn set_attribute(path: &Path, attrib: Attributes) -> bool {
use std::fs;
use std::fs::set_permissions;
use std::fs::File;
let bits = attrib.bits;
if &bits & Attributes::HIDDEN.bits == Attributes::HIDDEN.bits {
fs::rename(path, format!(".{}", path.to_str().unwrap())).is_ok();
} else if &bits & Attributes::READ_ONLY.bits == Attributes::READ_ONLY.bits{
let result = File::create(path);
if result.is_err() {
return false;
}
let file = result.unwrap();
let result_meta = file.metadata();
if result_meta.is_err() {
return false;
}
let meta = result_meta.unwrap();
let mut perms = meta.permissions();
perms.set_readonly(true);
return set_permissions(&path, perms).is_ok();
}
true
}
#[cfg(unix)]
pub fn has_attribute(file: &Path, attrib: Attributes) -> bool {
use std::fs::File;
if attrib ==Attributes::HIDDEN {
let option = file.file_name();
if option.is_none(){
return false;
}
let option = option.unwrap();
let str = option.to_str();
if str.is_none(){
return false;
}
str.unwrap().starts_with(".")
} else if attrib == Attributes::READ_ONLY{
let result = File::open(file);
if result.is_err() {
return false;
}
let file = result.unwrap();
let result_meta = file.metadata();
if result_meta.is_err() {
return false;
}
let meta = result_meta.unwrap();
meta.permissions().readonly()
}else {
false
}
}
#[cfg(unix)]
pub fn get_attributes(file: &Path) -> Result<Vec<Attributes>, String> {
let mut values: Vec<Attributes> = Vec::new();
if has_attribute(file, Attributes::READ_ONLY){
values.push(Attributes::READ_ONLY);
}
if has_attribute(file, Attributes::HIDDEN){
values.push(Attributes::HIDDEN);
}
Ok(values)
}