diff --git a/core-foundation-sys/src/bundle.rs b/core-foundation-sys/src/bundle.rs index 51746a6..d9eda5d 100644 --- a/core-foundation-sys/src/bundle.rs +++ b/core-foundation-sys/src/bundle.rs @@ -9,7 +9,8 @@ use libc::c_void; -use base::CFTypeID; +use base::{CFTypeID, CFAllocatorRef}; +use url::CFURLRef; use dictionary::CFDictionaryRef; use string::CFStringRef; @@ -22,10 +23,13 @@ extern { /* * CFBundle.h */ + pub fn CFBundleCreate(allocator: CFAllocatorRef, bundleURL: CFURLRef) -> CFBundleRef; + pub fn CFBundleGetBundleWithIdentifier(bundleID: CFStringRef) -> CFBundleRef; pub fn CFBundleGetFunctionPointerForName(bundle: CFBundleRef, function_name: CFStringRef) -> *const c_void; pub fn CFBundleGetMainBundle() -> CFBundleRef; pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef; pub fn CFBundleGetTypeID() -> CFTypeID; + pub fn CFBundleCopyExecutableURL(bundle: CFBundleRef) -> CFURLRef; } diff --git a/core-foundation/src/bundle.rs b/core-foundation/src/bundle.rs index 8344225..49a24c3 100644 --- a/core-foundation/src/bundle.rs +++ b/core-foundation/src/bundle.rs @@ -10,9 +10,10 @@ //! Core Foundation Bundle Type pub use core_foundation_sys::bundle::*; -use core_foundation_sys::base::CFRelease; +use core_foundation_sys::base::{CFRelease, kCFAllocatorDefault}; -use base::{TCFType}; +use base::TCFType; +use url::CFURL; use dictionary::CFDictionary; /// A Bundle type. @@ -27,6 +28,17 @@ impl Drop for CFBundle { } impl CFBundle { + pub fn new(bundleURL: CFURL) -> Option { + unsafe { + let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef()); + if bundle_ref.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(bundle_ref)) + } + } + } + pub fn main_bundle() -> CFBundle { unsafe { let bundle_ref = CFBundleGetMainBundle(); @@ -40,7 +52,40 @@ impl CFBundle { TCFType::wrap_under_get_rule(info_dictionary) } } + + pub fn exectuable_url(&self) -> Option { + unsafe { + let exe_url = CFBundleCopyExecutableURL(self.0); + if exe_url.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(exe_url)) + } + } + } } impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID); +#[test] +fn safari_exectuable_url() { + use string::CFString; + use url::{CFURL, kCFURLPOSIXPathStyle}; + + let cfstr_path = CFString::from_static_string("/Applications/Safari.app"); + let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); + let cfurl_executable = CFBundle::new(cfurl_path).expect("Safari not present").exectuable_url(); + assert!(cfurl_executable.is_some()); + assert_eq!(cfurl_executable.unwrap().absolute().get_file_system_path(kCFURLPOSIXPathStyle).to_string(), + "/Applications/Safari.app/Contents/MacOS/Safari"); +} + +#[test] +fn non_existant_bundle() { + use string::CFString; + use url::{CFURL, kCFURLPOSIXPathStyle}; + + let cfstr_path = CFString::from_static_string("/usr/local/foo"); + let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); + assert!(CFBundle::new(cfurl_path).is_none()); +}