1/*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <TargetConditionals.h>
24#include <libc.h>
25#include <sys/stat.h>
26#include <dlfcn.h>
27#include  "IOSystemConfiguration.h"
28
29
30#define SYSTEM_FRAMEWORK_DIR "/System/Library/Frameworks"
31#define SYSTEM_CONFIGURATION "SystemConfiguration.framework/SystemConfiguration"
32#define SC_FRAMEWORK	     SYSTEM_FRAMEWORK_DIR "/" SYSTEM_CONFIGURATION
33
34/* IOKIT_SC_SYMBOL
35 *
36 * - Tells the linker to pretend that _SYMBOL doesn't exist in OS X 10.7 and later.
37 * - Exports _SYMBOL as extern for OS X
38 * - Hides the _SYMBOL as __private_extern__ for iOS builds
39 *
40 */
41#if TARGET_OS_IPHONE
42#define IOKIT_SC_SYMBOL(_RETURN, _SYMBOL)   __private_extern__ _RETURN _io_##_SYMBOL
43#else
44#define IOKIT_SC_SYMBOL(_RETURN, _SYMBOL)   extern const char _SYMBOL##_tmp7 __asm("$ld$hide$os10.7$_" #_SYMBOL ); \
45                                            __attribute__ ((visibility("default"))) const char _SYMBOL##_tmp7 = 0; \
46                                            _RETURN _SYMBOL
47#endif
48
49const CFStringRef _io_kSCCompAnyRegex = CFSTR("[^/]+");
50const CFStringRef _io_kSCDynamicStoreDomainState = CFSTR("State:");
51
52static void * symAddrInSC(const char *name)
53{
54    static void * handle = NULL;
55
56    if (!handle) {
57        void            *locHandle;
58        const char      *framework = SC_FRAMEWORK;
59        struct stat     statbuf;
60        const char      *suffix = getenv("DYLD_IMAGE_SUFFIX");
61        char            path[MAXPATHLEN];
62
63        strlcpy(path, framework, sizeof(path));
64
65        if (suffix) {
66            strlcat(path, suffix, sizeof(path));
67        }
68
69        if (0 <= stat(path, &statbuf)) {
70            locHandle = dlopen(path,      RTLD_LAZY);
71        } else {
72            locHandle = dlopen(framework, RTLD_LAZY);
73        }
74
75        if (locHandle) {
76            handle = locHandle;
77        }
78    }
79
80    if (handle)
81        return dlsym(handle, name);
82    else
83        return NULL;
84}
85
86IOKIT_SC_SYMBOL(Boolean, SCDynamicStoreAddWatchedKey)(
87        SCDynamicStoreRef		store,
88	 CFStringRef			key,
89	 Boolean				isRegex)
90{
91    static typeof (SCDynamicStoreAddWatchedKey) *dyfunc;
92    if (!dyfunc)
93        dyfunc = symAddrInSC("SCDynamicStoreAddWatchedKey");
94
95    if (dyfunc)
96        return (*dyfunc)(store, key, isRegex);
97    else
98        return false;
99}
100
101
102IOKIT_SC_SYMBOL(int, SCError)()
103{
104    static typeof (SCError) *dyfunc;
105    if (!dyfunc)
106	dyfunc = symAddrInSC("SCError");
107    if (dyfunc)
108	return (*dyfunc)();
109    else
110	return kSCStatusFailed;
111}
112
113
114
115IOKIT_SC_SYMBOL(CFDictionaryRef, SCDynamicStoreCopyMultiple)(
116	SCDynamicStoreRef		store,
117    CFArrayRef			keys,
118    CFArrayRef			patterns
119)
120{
121    static typeof (SCDynamicStoreCopyMultiple) *dyfunc;
122    if (!dyfunc)
123	dyfunc = symAddrInSC("SCDynamicStoreCopyMultiple");
124    if (dyfunc)
125	return (*dyfunc)(store, keys, patterns);
126    else
127	return NULL;
128}
129
130
131IOKIT_SC_SYMBOL(CFTypeRef, SCDynamicStoreCopyValue)(
132	SCDynamicStoreRef		store,
133	CFStringRef			key
134)
135{
136    static typeof (SCDynamicStoreCopyValue) *dyfunc;
137    if (!dyfunc)
138	dyfunc = symAddrInSC("SCDynamicStoreCopyValue");
139    if (dyfunc)
140	return (*dyfunc)(store, key);
141    else
142	return NULL;
143}
144
145
146IOKIT_SC_SYMBOL(SCDynamicStoreRef, SCDynamicStoreCreate)(
147	CFAllocatorRef		allocator,
148	CFStringRef			name,
149	SCDynamicStoreCallBack	callout,
150	SCDynamicStoreContext	*context
151)
152{
153    static typeof (SCDynamicStoreCreate) *dyfunc;
154    if (!dyfunc)
155	dyfunc = symAddrInSC("SCDynamicStoreCreate");
156    if (dyfunc)
157	return (*dyfunc)(allocator, name, callout, context);
158    else
159	return NULL;
160}
161
162
163IOKIT_SC_SYMBOL(CFRunLoopSourceRef, SCDynamicStoreCreateRunLoopSource)(
164    CFAllocatorRef		allocator,
165	SCDynamicStoreRef		store,
166	CFIndex			order
167)
168{
169    static typeof (SCDynamicStoreCreateRunLoopSource) *dyfunc;
170    if (!dyfunc)
171	dyfunc = symAddrInSC("SCDynamicStoreCreateRunLoopSource");
172    if (dyfunc)
173	return (*dyfunc)(allocator, store, order);
174    else
175	return NULL;
176}
177
178
179IOKIT_SC_SYMBOL(CFStringRef, SCDynamicStoreKeyCreate)(
180    CFAllocatorRef		allocator,
181	CFStringRef			fmt,
182	...
183)
184{
185    // Local implementation of a SCDynamicStore wrapper function
186    va_list val;
187
188    va_start(val, fmt);
189    CFStringRef key =
190	CFStringCreateWithFormatAndArguments(allocator, NULL, fmt, val);
191    va_end(val);
192
193    return key;
194}
195
196
197IOKIT_SC_SYMBOL(CFStringRef, SCDynamicStoreKeyCreatePreferences)(
198	CFAllocatorRef		allocator,
199	CFStringRef			prefsID,
200	SCPreferencesKeyType	keyType
201)
202{
203    static typeof (SCDynamicStoreKeyCreatePreferences) *dyfunc;
204    if (!dyfunc)
205	dyfunc = symAddrInSC("SCDynamicStoreKeyCreatePreferences");
206    if (dyfunc)
207	return (*dyfunc)(allocator, prefsID, keyType);
208    else
209	return NULL;
210}
211
212
213IOKIT_SC_SYMBOL(Boolean, SCDynamicStoreSetNotificationKeys)(
214	SCDynamicStoreRef		store,
215	CFArrayRef			keys,
216	CFArrayRef			patterns
217)
218{
219    static typeof (SCDynamicStoreSetNotificationKeys) *dyfunc;
220    if (!dyfunc)
221	dyfunc = symAddrInSC("SCDynamicStoreSetNotificationKeys");
222    if (dyfunc)
223	return (*dyfunc)(store, keys, patterns);
224    else
225	return false;
226}
227
228
229IOKIT_SC_SYMBOL(Boolean, SCDynamicStoreNotifyValue)(
230	SCDynamicStoreRef		store,
231	CFStringRef			key
232)
233{
234    static typeof (SCDynamicStoreNotifyValue) *dyfunc;
235    if (!dyfunc)
236	dyfunc = symAddrInSC("SCDynamicStoreNotifyValue");
237    if (dyfunc)
238	return (*dyfunc)(store, key);
239    else
240	return false;
241}
242
243IOKIT_SC_SYMBOL(Boolean, SCDynamicStoreSetValue)(
244    SCDynamicStoreRef		store,
245	CFStringRef			key,
246	CFPropertyListRef		value
247)
248{
249    static typeof (SCDynamicStoreSetValue) *dyfunc;
250    if (!dyfunc)
251	dyfunc = symAddrInSC("SCDynamicStoreSetValue");
252    if (dyfunc)
253	return (*dyfunc)(store, key, value);
254    else
255	return false;
256}
257
258
259IOKIT_SC_SYMBOL(Boolean, SCPreferencesApplyChanges)(
260	SCPreferencesRef		prefs
261)
262{
263    static typeof (SCPreferencesApplyChanges) *dyfunc;
264    if (!dyfunc)
265	dyfunc = symAddrInSC("SCPreferencesApplyChanges");
266    if (dyfunc)
267	return (*dyfunc)(prefs);
268    else
269	return false;
270}
271
272
273IOKIT_SC_SYMBOL(Boolean, SCPreferencesCommitChanges)(
274	SCPreferencesRef		prefs
275)
276{
277    static typeof (SCPreferencesCommitChanges) *dyfunc;
278    if (!dyfunc)
279	dyfunc = symAddrInSC("SCPreferencesCommitChanges");
280    if (dyfunc)
281	return (*dyfunc)(prefs);
282    else
283	return false;
284}
285
286
287IOKIT_SC_SYMBOL(SCPreferencesRef, SCPreferencesCreate)(
288	CFAllocatorRef		allocator,
289	CFStringRef			name,
290	CFStringRef			prefsID
291)
292{
293    static typeof (SCPreferencesCreate) *dyfunc;
294    if (!dyfunc)
295	dyfunc = symAddrInSC("SCPreferencesCreate");
296    if (dyfunc)
297	return (*dyfunc)(allocator, name, prefsID);
298    else
299	return NULL;
300}
301
302
303IOKIT_SC_SYMBOL(SCPreferencesRef, SCPreferencesCreateWithAuthorization)(
304	CFAllocatorRef		allocator,
305	CFStringRef		name,
306	CFStringRef		prefsID,
307	AuthorizationRef	authorization
308)
309{
310    static typeof (SCPreferencesCreateWithAuthorization) *dyfunc;
311    if (!dyfunc)
312	dyfunc = symAddrInSC("SCPreferencesCreateWithAuthorization");
313    if (dyfunc)
314	return (*dyfunc)(allocator, name, prefsID, authorization);
315    else
316	return NULL;
317}
318
319
320IOKIT_SC_SYMBOL(CFPropertyListRef, SCPreferencesGetValue)(
321	SCPreferencesRef		prefs,
322	CFStringRef			key
323)
324{
325    static typeof (SCPreferencesGetValue) *dyfunc;
326    if (!dyfunc)
327	dyfunc = symAddrInSC("SCPreferencesGetValue");
328    if (dyfunc)
329	return (*dyfunc)(prefs, key);
330    else
331	return NULL;
332}
333
334
335IOKIT_SC_SYMBOL(Boolean, SCPreferencesLock)(
336	SCPreferencesRef		prefs,
337	Boolean			wait
338)
339{
340    static typeof (SCPreferencesLock) *dyfunc;
341    if (!dyfunc)
342	dyfunc = symAddrInSC("SCPreferencesLock");
343    if (dyfunc)
344	return (*dyfunc)(prefs, wait);
345    else
346	return false;
347}
348
349
350IOKIT_SC_SYMBOL(Boolean, SCPreferencesRemoveValue)(
351	SCPreferencesRef		prefs,
352	CFStringRef			key
353)
354{
355    static typeof (SCPreferencesRemoveValue) *dyfunc;
356    if (!dyfunc)
357	dyfunc = symAddrInSC("SCPreferencesRemoveValue");
358    if (dyfunc)
359	return (*dyfunc)(prefs, key);
360    else
361	return false;
362}
363
364
365IOKIT_SC_SYMBOL(Boolean, SCPreferencesSetValue)(
366	SCPreferencesRef		prefs,
367	CFStringRef				key,
368	CFPropertyListRef		value
369)
370{
371    static typeof (SCPreferencesSetValue) *dyfunc;
372    if (!dyfunc)
373		dyfunc = symAddrInSC("SCPreferencesSetValue");
374    if (dyfunc)
375		return (*dyfunc)(prefs, key, value);
376    else
377		return false;
378}
379
380
381IOKIT_SC_SYMBOL(Boolean, SCPreferencesUnlock)(
382	SCPreferencesRef		prefs
383)
384{
385    static typeof (SCPreferencesUnlock) *dyfunc;
386    if (!dyfunc)
387	dyfunc = symAddrInSC("SCPreferencesUnlock");
388    if (dyfunc)
389	return (*dyfunc)(prefs);
390    else
391	return false;
392}
393