]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDOpen.c
configd-42.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDOpen.c
1 /*
2 * Copyright (c) 2000 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 <mach/mach.h>
34 #include <mach/mach_error.h>
35 #include <servers/bootstrap.h>
36
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCPrivate.h>
39 #include "SCDynamicStoreInternal.h"
40 #include "config.h" /* MiG generated file */
41
42 static CFStringRef
43 __SCDynamicStoreCopyDescription(CFTypeRef cf) {
44 CFAllocatorRef allocator = CFGetAllocator(cf);
45 CFMutableStringRef result;
46
47 result = CFStringCreateMutable(allocator, 0);
48 CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
49 CFStringAppendFormat(result, NULL, CFSTR("}"));
50
51 return result;
52 }
53
54
55 static void
56 __SCDynamicStoreDeallocate(CFTypeRef cf)
57 {
58 CFIndex keyCnt;
59 int oldThreadState;
60 int sc_status;
61 kern_return_t status;
62 SCDynamicStoreRef store = (SCDynamicStoreRef)cf;
63 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
64
65 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:"));
66
67 (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState);
68
69 /* Remove notification keys */
70 if ((keyCnt = CFSetGetCount(storePrivate->keys)) > 0) {
71 void **watchedKeys;
72 CFArrayRef keysToRemove;
73 CFIndex i;
74
75 watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
76 CFSetGetValues(storePrivate->keys, watchedKeys);
77 keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
78 CFAllocatorDeallocate(NULL, watchedKeys);
79 for (i=0; i<keyCnt; i++) {
80 (void) SCDynamicStoreRemoveWatchedKey(store,
81 CFArrayGetValueAtIndex(keysToRemove, i),
82 FALSE);
83 }
84 CFRelease(keysToRemove);
85 }
86
87 /* Remove regex notification keys */
88 if ((keyCnt = CFSetGetCount(storePrivate->reKeys)) > 0) {
89 void **watchedKeys;
90 CFArrayRef keysToRemove;
91 CFIndex i;
92
93 watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
94 CFSetGetValues(storePrivate->reKeys, watchedKeys);
95 keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
96 CFAllocatorDeallocate(NULL, watchedKeys);
97 for (i=0; i<keyCnt; i++) {
98 (void) SCDynamicStoreRemoveWatchedKey(store,
99 CFArrayGetValueAtIndex(keysToRemove, i),
100 TRUE);
101 }
102 CFRelease(keysToRemove);
103 }
104
105 /* Remove/cancel any outstanding notification requests. */
106 (void) SCDynamicStoreNotifyCancel(store);
107
108 if (storePrivate->server && storePrivate->locked) {
109 (void) SCDynamicStoreUnlock(store); /* release the lock */
110 }
111
112 if (storePrivate->server != MACH_PORT_NULL) {
113 status = configclose(storePrivate->server, (int *)&sc_status);
114 if (status != KERN_SUCCESS) {
115 if (status != MACH_SEND_INVALID_DEST)
116 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status));
117 }
118
119 (void) mach_port_destroy(mach_task_self(), storePrivate->server);
120 storePrivate->server = MACH_PORT_NULL;
121 }
122
123 (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldThreadState);
124 pthread_testcancel();
125
126 /* release any callback context info */
127 if (storePrivate->rlsContext.release) {
128 storePrivate->rlsContext.release(storePrivate->rlsContext.info);
129 }
130
131 /* release any keys being watched */
132 CFRelease(storePrivate->keys);
133 CFRelease(storePrivate->reKeys);
134
135 return;
136 }
137
138
139 static CFTypeID __kSCDynamicStoreTypeID = _kCFRuntimeNotATypeID;
140
141
142 static const CFRuntimeClass __SCDynamicStoreClass = {
143 0, // version
144 "SCDynamicStore", // className
145 NULL, // init
146 NULL, // copy
147 __SCDynamicStoreDeallocate, // dealloc
148 NULL, // equal
149 NULL, // hash
150 NULL, // copyFormattingDesc
151 __SCDynamicStoreCopyDescription // copyDebugDesc
152 };
153
154
155 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
156
157
158 static void
159 __SCDynamicStoreInitialize(void) {
160 __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
161 return;
162 }
163
164
165 SCDynamicStoreRef
166 __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator,
167 const CFStringRef name,
168 SCDynamicStoreCallBack callout,
169 SCDynamicStoreContext *context)
170 {
171 SCDynamicStorePrivateRef store;
172 UInt32 size;
173
174 /* initialize runtime */
175 pthread_once(&initialized, __SCDynamicStoreInitialize);
176
177 /* allocate session */
178 size = sizeof(SCDynamicStorePrivate) - sizeof(CFRuntimeBase);
179 store = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator,
180 __kSCDynamicStoreTypeID,
181 size,
182 NULL);
183 if (!store) {
184 return NULL;
185 }
186
187 /* server side of the "configd" session */
188 store->server = MACH_PORT_NULL;
189
190 /* flags */
191 store->locked = FALSE;
192
193 /* SCDKeys being watched */
194 store->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
195 store->reKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
196
197 /* Notification status */
198 store->notifyStatus = NotifierNotRegistered;
199
200 /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */
201 store->rlsRefs = 0;
202 store->rls = NULL;
203 store->rlsFunction = callout;
204 store->rlsContext.info = NULL;
205 store->rlsContext.retain = NULL;
206 store->rlsContext.release = NULL;
207 store->rlsContext.copyDescription = NULL;
208 if (context) {
209 bcopy(context, &store->rlsContext, sizeof(SCDynamicStoreContext));
210 if (context->retain) {
211 store->rlsContext.info = (void *)context->retain(context->info);
212 }
213 }
214
215 /* "client" information associated with SCDynamicStoreNotifyCallback() */
216 store->callbackFunction = NULL;
217 store->callbackArgument = NULL;
218 store->callbackPort = NULL;
219 store->callbackRunLoop = NULL;
220 store->callbackRunLoopSource = NULL;
221
222 /* "server" information associated with SCDynamicStoreNotifyMachPort(); */
223 store->notifyPort = MACH_PORT_NULL;
224 store->notifyPortIdentifier = 0;
225
226 /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */
227 store->notifyFile = -1;
228 store->notifyFileIdentifier = 0;
229
230 /* "server" information associated with SCDynamicStoreNotifySignal(); */
231 store->notifySignal = 0;
232 store->notifySignalTask = TASK_NULL;
233
234 return (SCDynamicStoreRef)store;
235 }
236
237
238 SCDynamicStoreRef
239 SCDynamicStoreCreate(CFAllocatorRef allocator,
240 CFStringRef name,
241 SCDynamicStoreCallBack callout,
242 SCDynamicStoreContext *context)
243 {
244 SCDynamicStoreRef store;
245 SCDynamicStorePrivateRef storePrivate;
246 kern_return_t status;
247 mach_port_t bootstrap_port;
248 mach_port_t server;
249 CFDataRef xmlName; /* serialized name */
250 xmlData_t myNameRef;
251 CFIndex myNameLen;
252 int sc_status;
253
254 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:"));
255 SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name);
256
257 /*
258 * allocate and initialize a new session
259 */
260 store = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
261 storePrivate = (SCDynamicStorePrivateRef)store;
262
263 status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
264 if (status != KERN_SUCCESS) {
265 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
266 CFRelease(store);
267 _SCErrorSet(status);
268 return NULL;
269 }
270
271 status = bootstrap_look_up(bootstrap_port, SCD_SERVER, &server);
272 switch (status) {
273 case BOOTSTRAP_SUCCESS :
274 /* service currently registered, "a good thing" (tm) */
275 break;
276 case BOOTSTRAP_UNKNOWN_SERVICE :
277 /* service not currently registered, try again later */
278 CFRelease(store);
279 _SCErrorSet(status);
280 return NULL;
281 break;
282 default :
283 #ifdef DEBUG
284 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_status: %s"), mach_error_string(status));
285 #endif /* DEBUG */
286 CFRelease(store);
287 _SCErrorSet(status);
288 return NULL;
289 }
290
291 /* serialize the name */
292 xmlName = CFPropertyListCreateXMLData(NULL, name);
293 myNameRef = (xmlData_t)CFDataGetBytePtr(xmlName);
294 myNameLen = CFDataGetLength(xmlName);
295
296 /* open a new session with the server */
297 status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status);
298
299 /* clean up */
300 CFRelease(xmlName);
301
302 if (status != KERN_SUCCESS) {
303 if (status != MACH_SEND_INVALID_DEST)
304 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status));
305 CFRelease(store);
306 _SCErrorSet(status);
307 return NULL;
308 }
309
310 if (sc_status != kSCStatusOK) {
311 CFRelease(store);
312 _SCErrorSet(sc_status);
313 return FALSE;
314 }
315
316 SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server);
317 return store;
318 }
319
320
321 CFTypeID
322 SCDynamicStoreGetTypeID(void) {
323 return __kSCDynamicStoreTypeID;
324 }