Skip to content

Commit 29ae251

Browse files
committed
Merge branch 'add-basic-dynamicstore-wrapper'
2 parents 05a6b41 + 6d4d428 commit 29ae251

File tree

6 files changed

+179
-9
lines changed

6 files changed

+179
-9
lines changed

rustfmt.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Activation of features, almost objectively better ;)
2+
reorder_imports = true
3+
reorder_imported_names = true
4+
reorder_imports_in_group = true
5+
use_try_shorthand = true
6+
condense_wildcard_suffices = true
7+
normalize_comments = true
8+
wrap_comments = true
9+
10+
# Heavily subjective style choices
11+
comment_width = 100

system-configuration-sys/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ license = "MIT/Apache-2.0"
1010
build = "build.rs"
1111

1212
[dependencies]
13-
core-foundation = "0.4"
14-
core-foundation-sys = "0.4"
13+
core-foundation-sys = { git = "https://github.com/servo/core-foundation-rs", version = "0.4.4" }
1514

1615
[build-dependencies]
1716
bindgen = "0.31"

system-configuration/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ repository = "https://github.com/mullvad/system-configuration-rs"
99
license = "MIT/Apache-2.0"
1010

1111
[dependencies]
12+
core-foundation = { git = "https://github.com/servo/core-foundation-rs", version = "0.4.4" }
13+
core-foundation-sys = { git = "https://github.com/servo/core-foundation-rs", version = "0.4.4" }
14+
15+
system-configuration-sys = { path = "../system-configuration-sys" }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
extern crate system_configuration;
2+
extern crate system_configuration_sys;
3+
4+
extern crate core_foundation;
5+
extern crate core_foundation_sys;
6+
7+
use core_foundation::array::CFArray;
8+
use core_foundation::base::TCFType;
9+
use core_foundation::dictionary::CFDictionary;
10+
use core_foundation::string::{CFString, CFStringRef};
11+
12+
use system_configuration::dynamic_store::SCDynamicStore;
13+
14+
fn main() {
15+
unsafe {
16+
let store = SCDynamicStore::create("my-test-dyn-store");
17+
println!("Created dynamic store");
18+
19+
let ipv4_dict = store
20+
.get("State:/Network/Global/IPv4")
21+
.expect("Unable to find global settings")
22+
.downcast::<_, CFDictionary>()
23+
.expect("Global IPv4 settings not a dictionary");
24+
println!("Got IPv4 global property list");
25+
26+
let pri_service_id_ptr = ipv4_dict
27+
.find2(&CFString::from_static_string("PrimaryService"))
28+
.expect("No PrimaryService");
29+
let pri_service_id = CFString::wrap_under_get_rule(pri_service_id_ptr as CFStringRef);
30+
31+
let pri_service_path =
32+
CFString::new(&format!("State:/Network/Service/{}/DNS", pri_service_id));
33+
println!("PrimaryService path: {}", pri_service_path);
34+
35+
let server_addresses_key = CFString::from_static_string("ServerAddresses");
36+
let server_addresses_value = CFArray::from_CFTypes(&[
37+
CFString::from_static_string("8.8.8.8"),
38+
CFString::from_static_string("8.8.4.4"),
39+
]);
40+
let dns_dictionary =
41+
CFDictionary::from_CFType_pairs(&[(server_addresses_key, server_addresses_value)]);
42+
43+
let success = store.set(pri_service_path, &dns_dictionary);
44+
println!("success? {}", success);
45+
}
46+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2017 Amagicom AB.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use core_foundation::base::TCFType;
10+
use core_foundation::boolean::CFBoolean;
11+
use core_foundation::dictionary::CFDictionary;
12+
use core_foundation::propertylist::{CFPropertyList, CFPropertyListSubClass};
13+
use core_foundation::string::CFString;
14+
use core_foundation_sys::base::{CFRelease, kCFAllocatorDefault};
15+
16+
use system_configuration_sys::dynamic_store::*;
17+
18+
use std::ptr;
19+
20+
/// Access to the key-value pairs in the dynamic store of a running system.
21+
pub struct SCDynamicStore(SCDynamicStoreRef);
22+
23+
impl Drop for SCDynamicStore {
24+
fn drop(&mut self) {
25+
unsafe { CFRelease(self.as_CFTypeRef()) }
26+
}
27+
}
28+
29+
impl_TCFType!(SCDynamicStore, SCDynamicStoreRef, SCDynamicStoreGetTypeID);
30+
31+
impl SCDynamicStore {
32+
/// Creates a new session used to interact with the dynamic store maintained by the System
33+
/// Configuration server.
34+
pub fn create<S: Into<CFString>>(name: S) -> Self {
35+
let cf_name = name.into();
36+
unsafe {
37+
let store = SCDynamicStoreCreate(
38+
kCFAllocatorDefault,
39+
cf_name.as_concrete_TypeRef(),
40+
None,
41+
ptr::null_mut(),
42+
);
43+
SCDynamicStore::wrap_under_create_rule(store)
44+
}
45+
}
46+
47+
/// Creates a new session used to interact with the dynamic store maintained by the System
48+
/// Configuration server. Uses [`SCDynamicStoreCreateWithOptions`] underneath and sets
49+
/// `kSCDynamicStoreUseSessionKeys` to true.
50+
///
51+
/// [`SCDynamicStoreCreateWithOptions`]: https://developer.apple.com/documentation/systemconfiguration/1437818-scdynamicstorecreatewithoptions?language=objc
52+
pub fn create_with_session_keys<S: Into<CFString>>(name: S) -> Self {
53+
let cf_name = name.into();
54+
unsafe {
55+
let store_options = CFDictionary::from_CFType_pairs(&[
56+
(
57+
CFString::wrap_under_create_rule(kSCDynamicStoreUseSessionKeys),
58+
CFBoolean::true_value(),
59+
),
60+
]);
61+
let store = SCDynamicStoreCreateWithOptions(
62+
kCFAllocatorDefault,
63+
cf_name.as_concrete_TypeRef(),
64+
store_options.as_concrete_TypeRef(),
65+
None,
66+
ptr::null_mut(),
67+
);
68+
SCDynamicStore::wrap_under_create_rule(store)
69+
}
70+
}
71+
72+
/// If the given key exists in the store, the associated value is returned.
73+
///
74+
/// Use `CFPropertyList::downcast` to cast the result into the correct type.
75+
pub fn get<S: Into<CFString>>(&self, key: S) -> Option<CFPropertyList> {
76+
let cf_key = key.into();
77+
unsafe {
78+
let dict_ref =
79+
SCDynamicStoreCopyValue(self.as_concrete_TypeRef(), cf_key.as_concrete_TypeRef());
80+
if dict_ref != ptr::null() {
81+
Some(CFPropertyList::wrap_under_create_rule(dict_ref))
82+
} else {
83+
None
84+
}
85+
}
86+
}
87+
88+
/// Sets the value of the given key. Overwrites existing values.
89+
/// Returns `true` on success, false on failure.
90+
pub fn set<S: Into<CFString>, R, V: CFPropertyListSubClass<R>>(
91+
&self,
92+
key: S,
93+
value: &V,
94+
) -> bool {
95+
self.set_raw(key, &value.to_CFPropertyList())
96+
}
97+
98+
/// Sets the value of the given key. Overwrites existing values.
99+
/// Returns `true` on success, false on failure.
100+
pub fn set_raw<S: Into<CFString>>(&self, key: S, value: &CFPropertyList) -> bool {
101+
let cf_key = key.into();
102+
let success = unsafe {
103+
SCDynamicStoreSetValue(
104+
self.as_concrete_TypeRef(),
105+
cf_key.as_concrete_TypeRef(),
106+
value.as_concrete_TypeRef(),
107+
)
108+
};
109+
success != 0
110+
}
111+
}

system-configuration/src/lib.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
#[cfg(test)]
2-
mod tests {
3-
#[test]
4-
fn it_works() {
5-
assert_eq!(2 + 2, 4);
6-
}
7-
}
1+
#[macro_use]
2+
extern crate core_foundation;
3+
extern crate core_foundation_sys;
4+
extern crate system_configuration_sys;
5+
6+
pub mod dynamic_store;

0 commit comments

Comments
 (0)