use std::path::Path;
use std::ffi::CString;
use std::ptr;
use objc::runtime as objc;
use error::Error;
use error::Error::*;
use std::os::raw::c_void;
#[link(kind="framework", name="Cocoa")]
extern "C" {
#[no_mangle]
static NSURLIsExcludedFromBackupKey: *const c_void;
}
pub fn exclude_from_backups<P: AsRef<Path>>(path: P) -> Result<(), Error> {
let path_cstr = CString::new(path.as_ref().to_str().ok_or(IncompatiblePathCharset)?)
.map_err(|_|IncompatiblePathCharset)?;
unsafe {
let nsstring_cls = objc::Class::get("NSString").ok_or(ObjcCallFailed)?;
let nsnumber_cls = objc::Class::get("NSNumber").ok_or(ObjcCallFailed)?;
let nsurl_cls = objc::Class::get("NSURL").ok_or(ObjcCallFailed)?;
let path_nsstr: *mut objc::Object = msg_send![nsstring_cls, stringWithUTF8String:path_cstr.as_ptr()];
if path_nsstr.is_null() {
return Err(ObjcCallFailed);
}
let yes_nsnumber: *mut objc::Object = msg_send![nsnumber_cls, numberWithBool:objc::YES];
if yes_nsnumber.is_null() {
return Err(ObjcCallFailed);
}
let url: *mut objc::Object = msg_send![nsurl_cls, fileURLWithPath:path_nsstr isDirectory:objc::YES];
if url.is_null() {
return Err(ObjcCallFailed);
}
let nil_err: *mut *mut objc::Object = ptr::null_mut();
let res: objc::BOOL = msg_send![url, setResourceValue:yes_nsnumber forKey:NSURLIsExcludedFromBackupKey error:nil_err];
if res != objc::YES {
return Err(SystemCallFailed);
}
}
Ok(())
}
#[test]
fn test_excluding() {
use std::fs;
let path = Path::new("/tmp/exclude_from_backups_test_dir");
if !path.exists() {
fs::create_dir(path).unwrap();
}
exclude_from_backups(&path).unwrap();
let _ = fs::remove_dir_all(path);
}