2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
32 * March 24, 2000 Allan Nathanson <ajn@apple.com>
37 #include <mach/mach.h>
38 #include <mach/mach_error.h>
39 #include <servers/bootstrap.h>
41 #include <SystemConfiguration/SystemConfiguration.h>
42 #include <SystemConfiguration/SCPrivate.h>
43 #include "SCDynamicStoreInternal.h"
44 #include "config.h" /* MiG generated file */
47 __SCDynamicStoreCopyDescription(CFTypeRef cf
) {
48 CFAllocatorRef allocator
= CFGetAllocator(cf
);
49 CFMutableStringRef result
;
51 result
= CFStringCreateMutable(allocator
, 0);
52 CFStringAppendFormat(result
, NULL
, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf
, allocator
);
53 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
60 __SCDynamicStoreDeallocate(CFTypeRef cf
)
65 SCDynamicStoreRef store
= (SCDynamicStoreRef
)cf
;
66 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
68 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__SCDynamicStoreDeallocate:"));
70 (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, &oldThreadState
);
72 /* Remove/cancel any outstanding notification requests. */
73 (void) SCDynamicStoreNotifyCancel(store
);
75 if (storePrivate
->server
&& storePrivate
->locked
) {
76 (void) SCDynamicStoreUnlock(store
); /* release the lock */
79 if (storePrivate
->server
!= MACH_PORT_NULL
) {
80 status
= configclose(storePrivate
->server
, (int *)&sc_status
);
81 if (status
!= KERN_SUCCESS
) {
82 if (status
!= MACH_SEND_INVALID_DEST
)
83 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("configclose(): %s"), mach_error_string(status
));
86 (void) mach_port_destroy(mach_task_self(), storePrivate
->server
);
87 storePrivate
->server
= MACH_PORT_NULL
;
90 (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, &oldThreadState
);
93 /* release any callback context info */
94 if (storePrivate
->rlsContext
.release
) {
95 storePrivate
->rlsContext
.release(storePrivate
->rlsContext
.info
);
98 /* release any keys being watched */
99 CFRelease(storePrivate
->keys
);
100 CFRelease(storePrivate
->patterns
);
106 static CFTypeID __kSCDynamicStoreTypeID
= _kCFRuntimeNotATypeID
;
109 static const CFRuntimeClass __SCDynamicStoreClass
= {
111 "SCDynamicStore", // className
114 __SCDynamicStoreDeallocate
, // dealloc
117 NULL
, // copyFormattingDesc
118 __SCDynamicStoreCopyDescription
// copyDebugDesc
122 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
125 __SCDynamicStoreInitialize(void) {
126 __kSCDynamicStoreTypeID
= _CFRuntimeRegisterClass(&__SCDynamicStoreClass
);
131 SCDynamicStorePrivateRef
132 __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator
,
133 const CFStringRef name
,
134 SCDynamicStoreCallBack callout
,
135 SCDynamicStoreContext
*context
)
138 SCDynamicStorePrivateRef storePrivate
;
140 /* initialize runtime */
141 pthread_once(&initialized
, __SCDynamicStoreInitialize
);
143 /* allocate session */
144 size
= sizeof(SCDynamicStorePrivate
) - sizeof(CFRuntimeBase
);
145 storePrivate
= (SCDynamicStorePrivateRef
)_CFRuntimeCreateInstance(allocator
,
146 __kSCDynamicStoreTypeID
,
153 /* server side of the "configd" session */
154 storePrivate
->server
= MACH_PORT_NULL
;
157 storePrivate
->locked
= FALSE
;
159 /* Notification status */
160 storePrivate
->notifyStatus
= NotifierNotRegistered
;
162 /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */
163 storePrivate
->rlsRefs
= 0;
164 storePrivate
->rls
= NULL
;
165 storePrivate
->rlsFunction
= callout
;
166 storePrivate
->rlsContext
.info
= NULL
;
167 storePrivate
->rlsContext
.retain
= NULL
;
168 storePrivate
->rlsContext
.release
= NULL
;
169 storePrivate
->rlsContext
.copyDescription
= NULL
;
171 bcopy(context
, &storePrivate
->rlsContext
, sizeof(SCDynamicStoreContext
));
172 if (context
->retain
) {
173 storePrivate
->rlsContext
.info
= (void *)context
->retain(context
->info
);
177 /* "client" information associated with SCDynamicStoreNotifyCallback() */
178 storePrivate
->callbackFunction
= NULL
;
179 storePrivate
->callbackArgument
= NULL
;
180 storePrivate
->callbackPort
= NULL
;
181 storePrivate
->callbackRunLoop
= NULL
;
182 storePrivate
->callbackRunLoopSource
= NULL
;
184 /* "server" information associated with SCDynamicStoreSetNotificationKeys() */
185 storePrivate
->keys
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
186 storePrivate
->patterns
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
188 /* "server" information associated with SCDynamicStoreNotifyMachPort(); */
189 storePrivate
->notifyPort
= MACH_PORT_NULL
;
190 storePrivate
->notifyPortIdentifier
= 0;
192 /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */
193 storePrivate
->notifyFile
= -1;
194 storePrivate
->notifyFileIdentifier
= 0;
196 /* "server" information associated with SCDynamicStoreNotifySignal(); */
197 storePrivate
->notifySignal
= 0;
198 storePrivate
->notifySignalTask
= TASK_NULL
;
205 SCDynamicStoreCreate(CFAllocatorRef allocator
,
207 SCDynamicStoreCallBack callout
,
208 SCDynamicStoreContext
*context
)
210 SCDynamicStorePrivateRef storePrivate
;
211 kern_return_t status
;
212 mach_port_t bootstrap_port
;
214 CFStringRef bundleID
= NULL
;
217 CFDataRef utfName
; /* serialized name */
223 SCLog(TRUE
, LOG_DEBUG
, CFSTR("SCDynamicStoreCreate:"));
224 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
228 * allocate and initialize a new session
230 storePrivate
= __SCDynamicStoreCreatePrivate(allocator
, name
, callout
, context
);
232 status
= task_get_bootstrap_port(mach_task_self(), &bootstrap_port
);
233 if (status
!= KERN_SUCCESS
) {
234 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status
));
235 CFRelease(storePrivate
);
240 server_name
= getenv("SCD_SERVER");
242 server_name
= SCD_SERVER
;
245 status
= bootstrap_look_up(bootstrap_port
, server_name
, &server
);
247 case BOOTSTRAP_SUCCESS
:
248 /* service currently registered, "a good thing" (tm) */
250 case BOOTSTRAP_UNKNOWN_SERVICE
:
251 /* service not currently registered, try again later */
252 CFRelease(storePrivate
);
258 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("bootstrap_look_up() failed: status=%d"), status
);
260 CFRelease(storePrivate
);
265 /* serialize the name */
266 bundle
= CFBundleGetMainBundle();
268 bundleID
= CFBundleGetIdentifier(bundle
);
274 url
= CFBundleCopyExecutableURL(bundle
);
276 bundleID
= CFURLCopyPath(url
);
283 CFStringRef fullName
;
285 if (CFEqual(bundleID
, CFSTR("/"))) {
287 bundleID
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("(%d)"), getpid());
290 fullName
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@:%@"), bundleID
, name
);
297 if (!_SCSerializeString(name
, &utfName
, (void **)&myNameRef
, &myNameLen
)) {
299 _SCErrorSet(kSCStatusFailed
);
304 /* open a new session with the server */
305 status
= configopen(server
, myNameRef
, myNameLen
, &storePrivate
->server
, (int *)&sc_status
);
310 if (status
!= KERN_SUCCESS
) {
311 if (status
!= MACH_SEND_INVALID_DEST
)
312 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("configopen(): %s"), mach_error_string(status
));
313 CFRelease(storePrivate
);
318 if (sc_status
!= kSCStatusOK
) {
319 CFRelease(storePrivate
);
320 _SCErrorSet(sc_status
);
324 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" server port = %d"), storePrivate
->server
);
325 return (SCDynamicStoreRef
)storePrivate
;
330 SCDynamicStoreGetTypeID(void) {
331 pthread_once(&initialized
, __SCDynamicStoreInitialize
); /* initialize runtime */
332 return __kSCDynamicStoreTypeID
;