]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDOpen.c
configd-53.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDOpen.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * March 24, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include <stdlib.h>
34 #include <mach/mach.h>
35 #include <mach/mach_error.h>
36 #include <servers/bootstrap.h>
37
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include <SystemConfiguration/SCPrivate.h>
40 #include "SCDynamicStoreInternal.h"
41 #include "config.h" /* MiG generated file */
42
43 static CFStringRef
44 __SCDynamicStoreCopyDescription(CFTypeRef cf) {
45 CFAllocatorRef allocator = CFGetAllocator(cf);
46 CFMutableStringRef result;
47
48 result = CFStringCreateMutable(allocator, 0);
49 CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
50 CFStringAppendFormat(result, NULL, CFSTR("}"));
51
52 return result;
53 }
54
55
56 static void
57 __SCDynamicStoreDeallocate(CFTypeRef cf)
58 {
59 CFIndex keyCnt;
60 int oldThreadState;
61 int sc_status;
62 kern_return_t status;
63 SCDynamicStoreRef store = (SCDynamicStoreRef)cf;
64 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
65
66 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:"));
67
68 (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState);
69
70 /* Remove notification keys */
71 keyCnt = CFSetGetCount(storePrivate->keys);
72 if (keyCnt > 0) {
73 const void **watchedKeys;
74 CFArrayRef keysToRemove;
75 CFIndex i;
76
77 watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
78 CFSetGetValues(storePrivate->keys, watchedKeys);
79 keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
80 CFAllocatorDeallocate(NULL, watchedKeys);
81 for (i=0; i<keyCnt; i++) {
82 (void) SCDynamicStoreRemoveWatchedKey(store,
83 CFArrayGetValueAtIndex(keysToRemove, i),
84 FALSE);
85 }
86 CFRelease(keysToRemove);
87 }
88
89 /* Remove regex notification keys */
90 keyCnt = CFSetGetCount(storePrivate->reKeys);
91 if (keyCnt > 0) {
92 const void **watchedKeys;
93 CFArrayRef keysToRemove;
94 CFIndex i;
95
96 watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
97 CFSetGetValues(storePrivate->reKeys, watchedKeys);
98 keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
99 CFAllocatorDeallocate(NULL, watchedKeys);
100 for (i=0; i<keyCnt; i++) {
101 (void) SCDynamicStoreRemoveWatchedKey(store,
102 CFArrayGetValueAtIndex(keysToRemove, i),
103 TRUE);
104 }
105 CFRelease(keysToRemove);
106 }
107
108 /* Remove/cancel any outstanding notification requests. */
109 (void) SCDynamicStoreNotifyCancel(store);
110
111 if (storePrivate->server && storePrivate->locked) {
112 (void) SCDynamicStoreUnlock(store); /* release the lock */
113 }
114
115 if (storePrivate->server != MACH_PORT_NULL) {
116 status = configclose(storePrivate->server, (int *)&sc_status);
117 if (status != KERN_SUCCESS) {
118 if (status != MACH_SEND_INVALID_DEST)
119 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status));
120 }
121
122 (void) mach_port_destroy(mach_task_self(), storePrivate->server);
123 storePrivate->server = MACH_PORT_NULL;
124 }
125
126 (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldThreadState);
127 pthread_testcancel();
128
129 /* release any callback context info */
130 if (storePrivate->rlsContext.release) {
131 storePrivate->rlsContext.release(storePrivate->rlsContext.info);
132 }
133
134 /* release any keys being watched */
135 CFRelease(storePrivate->keys);
136 CFRelease(storePrivate->reKeys);
137
138 return;
139 }
140
141
142 static CFTypeID __kSCDynamicStoreTypeID = _kCFRuntimeNotATypeID;
143
144
145 static const CFRuntimeClass __SCDynamicStoreClass = {
146 0, // version
147 "SCDynamicStore", // className
148 NULL, // init
149 NULL, // copy
150 __SCDynamicStoreDeallocate, // dealloc
151 NULL, // equal
152 NULL, // hash
153 NULL, // copyFormattingDesc
154 __SCDynamicStoreCopyDescription // copyDebugDesc
155 };
156
157
158 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
159
160
161 static void
162 __SCDynamicStoreInitialize(void) {
163 __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
164 return;
165 }
166
167
168 SCDynamicStoreRef
169 __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator,
170 const CFStringRef name,
171 SCDynamicStoreCallBack callout,
172 SCDynamicStoreContext *context)
173 {
174 SCDynamicStorePrivateRef store;
175 UInt32 size;
176
177 /* initialize runtime */
178 pthread_once(&initialized, __SCDynamicStoreInitialize);
179
180 /* allocate session */
181 size = sizeof(SCDynamicStorePrivate) - sizeof(CFRuntimeBase);
182 store = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator,
183 __kSCDynamicStoreTypeID,
184 size,
185 NULL);
186 if (!store) {
187 return NULL;
188 }
189
190 /* server side of the "configd" session */
191 store->server = MACH_PORT_NULL;
192
193 /* flags */
194 store->locked = FALSE;
195
196 /* SCDKeys being watched */
197 store->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
198 store->reKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
199
200 /* Notification status */
201 store->notifyStatus = NotifierNotRegistered;
202
203 /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */
204 store->rlsRefs = 0;
205 store->rls = NULL;
206 store->rlsFunction = callout;
207 store->rlsContext.info = NULL;
208 store->rlsContext.retain = NULL;
209 store->rlsContext.release = NULL;
210 store->rlsContext.copyDescription = NULL;
211 if (context) {
212 bcopy(context, &store->rlsContext, sizeof(SCDynamicStoreContext));
213 if (context->retain) {
214 store->rlsContext.info = (void *)context->retain(context->info);
215 }
216 }
217
218 /* "client" information associated with SCDynamicStoreNotifyCallback() */
219 store->callbackFunction = NULL;
220 store->callbackArgument = NULL;
221 store->callbackPort = NULL;
222 store->callbackRunLoop = NULL;
223 store->callbackRunLoopSource = NULL;
224
225 /* "server" information associated with SCDynamicStoreNotifyMachPort(); */
226 store->notifyPort = MACH_PORT_NULL;
227 store->notifyPortIdentifier = 0;
228
229 /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */
230 store->notifyFile = -1;
231 store->notifyFileIdentifier = 0;
232
233 /* "server" information associated with SCDynamicStoreNotifySignal(); */
234 store->notifySignal = 0;
235 store->notifySignalTask = TASK_NULL;
236
237 return (SCDynamicStoreRef)store;
238 }
239
240
241 SCDynamicStoreRef
242 SCDynamicStoreCreate(CFAllocatorRef allocator,
243 CFStringRef name,
244 SCDynamicStoreCallBack callout,
245 SCDynamicStoreContext *context)
246 {
247 SCDynamicStoreRef store;
248 SCDynamicStorePrivateRef storePrivate;
249 kern_return_t status;
250 mach_port_t bootstrap_port;
251 mach_port_t server;
252 char *server_name;
253 CFDataRef xmlName; /* serialized name */
254 xmlData_t myNameRef;
255 CFIndex myNameLen;
256 int sc_status;
257
258 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:"));
259 SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name);
260
261 /*
262 * allocate and initialize a new session
263 */
264 store = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
265 storePrivate = (SCDynamicStorePrivateRef)store;
266
267 status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
268 if (status != KERN_SUCCESS) {
269 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
270 CFRelease(store);
271 _SCErrorSet(status);
272 return NULL;
273 }
274
275 server_name = getenv("SCD_SERVER");
276 if (!server_name) {
277 server_name = SCD_SERVER;
278 }
279
280 status = bootstrap_look_up(bootstrap_port, server_name, &server);
281 switch (status) {
282 case BOOTSTRAP_SUCCESS :
283 /* service currently registered, "a good thing" (tm) */
284 break;
285 case BOOTSTRAP_UNKNOWN_SERVICE :
286 /* service not currently registered, try again later */
287 CFRelease(store);
288 _SCErrorSet(status);
289 return NULL;
290 break;
291 default :
292 #ifdef DEBUG
293 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_status: %s"), mach_error_string(status));
294 #endif /* DEBUG */
295 CFRelease(store);
296 _SCErrorSet(status);
297 return NULL;
298 }
299
300 /* serialize the name */
301 if (!_SCSerialize(name, &xmlName, (void **)&myNameRef, &myNameLen)) {
302 _SCErrorSet(kSCStatusFailed);
303 return NULL;
304 }
305
306 /* open a new session with the server */
307 status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status);
308
309 /* clean up */
310 CFRelease(xmlName);
311
312 if (status != KERN_SUCCESS) {
313 if (status != MACH_SEND_INVALID_DEST)
314 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status));
315 CFRelease(store);
316 _SCErrorSet(status);
317 return NULL;
318 }
319
320 if (sc_status != kSCStatusOK) {
321 CFRelease(store);
322 _SCErrorSet(sc_status);
323 return FALSE;
324 }
325
326 SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server);
327 return store;
328 }
329
330
331 CFTypeID
332 SCDynamicStoreGetTypeID(void) {
333 return __kSCDynamicStoreTypeID;
334 }