2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * March 24, 2000 Allan Nathanson <ajn@apple.com>
33 #include <mach/mach.h>
34 #include <mach/mach_error.h>
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCPrivate.h>
39 #include "SCDynamicStoreInternal.h"
40 #include "config.h" /* MiG generated file */
42 /* framework variables */
43 Boolean _sc_debug
= FALSE
; /* TRUE if debugging enabled */
44 Boolean _sc_verbose
= FALSE
; /* TRUE if verbose logging enabled */
45 Boolean _sc_log
= TRUE
; /* TRUE if SCLog() output goes to syslog */
47 static const struct sc_errmsg
{
51 { kSCStatusAccessError
, "Permission denied" },
52 { kSCStatusFailed
, "Failed!" },
53 { kSCStatusInvalidArgument
, "Invalid argument" },
54 { kSCStatusKeyExists
, "Key already defined" },
55 { kSCStatusLocked
, "Lock already held" },
56 { kSCStatusMaxLink
, "Maximum link count exceeded" },
57 { kSCStatusNeedLock
, "Lock required for this operation" },
58 { kSCStatusNoStoreServer
, "Configuration daemon not (no longer) available" },
59 { kSCStatusNoStoreSession
, "Configuration daemon session not active" },
60 { kSCStatusNoConfigFile
, "Configuration file not found" },
61 { kSCStatusNoKey
, "No such key" },
62 { kSCStatusNoLink
, "No such link" },
63 { kSCStatusNoPrefsSession
, "Preference session not active" },
64 { kSCStatusNotifierActive
, "Notifier is currently active" },
65 { kSCStatusOK
, "Success!" },
66 { kSCStatusPrefsBusy
, "Configuration daemon busy" },
67 { kSCStatusReachabilityUnknown
, "Network reachability cannot be determined" },
68 { kSCStatusStale
, "Write attempted on stale version of object" },
70 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
73 #define USE_SCCOPYDESCRIPTION
74 #ifdef USE_SCCOPYDESCRIPTION
76 // from <CoreFoundation/CFVeryPrivate.h>
77 extern CFStringRef
_CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc
, CFStringRef (*copyDescFunc
)(void *, CFDictionaryRef
), CFDictionaryRef formatOptions
, CFStringRef format
, va_list arguments
);
80 _SCCopyDescription(void *info
, CFDictionaryRef formatOptions
)
82 CFMutableDictionaryRef nFormatOptions
;
85 CFTypeID type
= CFGetTypeID(info
);
88 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX1"), (const void **)&prefix1
)) {
92 if (type
== CFStringGetTypeID()) {
93 return CFStringCreateWithFormat(NULL
,
100 if (type
== CFBooleanGetTypeID()) {
101 return CFStringCreateWithFormat(NULL
,
105 CFBooleanGetValue(info
) ? "TRUE" : "FALSE");
108 if (type
== CFDataGetTypeID()) {
109 const u_int8_t
*data
;
112 CFMutableStringRef str
;
114 str
= CFStringCreateMutable(NULL
, 0);
115 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<data> 0x"), prefix1
);
117 data
= CFDataGetBytePtr(info
);
118 dataLen
= CFDataGetLength(info
);
119 for (i
= 0; i
< dataLen
; i
++) {
120 CFStringAppendFormat(str
, NULL
, CFSTR("%02x"), data
[i
]);
126 if (type
== CFNumberGetTypeID()) {
127 return CFStringCreateWithFormat(NULL
,
134 if (type
== CFDateGetTypeID()) {
135 CFGregorianDate gDate
;
139 tZone
= CFTimeZoneCopySystem();
140 gDate
= CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(info
), tZone
);
141 str
= CFStringCreateWithFormat(NULL
,
143 CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
151 CFTimeZoneGetName(tZone
));
156 if (!formatOptions
||
157 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX2"), (const void **)&prefix2
)) {
158 prefix2
= CFStringCreateCopy(NULL
, prefix1
);
162 nFormatOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, formatOptions
);
164 nFormatOptions
= CFDictionaryCreateMutable(NULL
,
166 &kCFTypeDictionaryKeyCallBacks
,
167 &kCFTypeDictionaryValueCallBacks
);
170 if (type
== CFArrayGetTypeID()) {
171 const void **elements
;
174 CFMutableStringRef str
;
176 str
= CFStringCreateMutable(NULL
, 0);
177 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<array> {"), prefix1
);
179 nElements
= CFArrayGetCount(info
);
181 elements
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
182 CFArrayGetValues(info
, CFRangeMake(0, nElements
), elements
);
183 for (i
=0; i
<nElements
; i
++) {
184 CFMutableStringRef nPrefix1
;
185 CFMutableStringRef nPrefix2
;
189 nStr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%u"), i
);
191 nPrefix1
= CFStringCreateMutable(NULL
, 0);
192 CFStringAppendFormat(nPrefix1
,
197 nPrefix2
= CFStringCreateMutable(NULL
, 0);
198 CFStringAppendFormat(nPrefix2
,
203 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
204 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
209 vStr
= _SCCopyDescription((void *)elements
[i
], nFormatOptions
);
210 CFStringAppendFormat(str
,
216 CFAllocatorDeallocate(NULL
, elements
);
218 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
220 CFRelease(nFormatOptions
);
224 if (type
== CFDictionaryGetTypeID()) {
228 CFMutableStringRef nPrefix1
;
229 CFMutableStringRef nPrefix2
;
230 CFMutableStringRef str
;
233 str
= CFStringCreateMutable(NULL
, 0);
234 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<dictionary> {"), prefix1
);
236 nElements
= CFDictionaryGetCount(info
);
238 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
239 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
240 CFDictionaryGetKeysAndValues(info
, keys
, values
);
241 for (i
=0; i
<nElements
; i
++) {
245 kStr
= _SCCopyDescription((void *)keys
[i
], NULL
);
247 nPrefix1
= CFStringCreateMutable(NULL
, 0);
248 CFStringAppendFormat(nPrefix1
,
253 nPrefix2
= CFStringCreateMutable(NULL
, 0);
254 CFStringAppendFormat(nPrefix2
,
259 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
260 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
265 vStr
= _SCCopyDescription((void *)values
[i
], nFormatOptions
);
266 CFStringAppendFormat(str
,
272 CFAllocatorDeallocate(NULL
, keys
);
273 CFAllocatorDeallocate(NULL
, values
);
275 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
277 CFRelease(nFormatOptions
);
285 cfStr
= CFCopyDescription(info
);
286 str
= CFStringCreateWithFormat(NULL
,
296 #endif /* USE_SCCOPYDESCRIPTION */
299 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
302 __private_extern__
void
303 __SCLog(int level
, CFStringRef str
)
307 lines
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR("\n"));
311 pthread_mutex_lock(&lock
);
312 for (i
=0; i
<CFArrayGetCount(lines
); i
++) {
315 line
= CFStringCreateExternalRepresentation(NULL
,
316 CFArrayGetValueAtIndex(lines
, i
),
317 kCFStringEncodingMacRoman
,
320 syslog (level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
324 pthread_mutex_unlock(&lock
);
332 __private_extern__
void
333 __SCPrint(FILE *stream
, CFStringRef str
)
337 line
= CFStringCreateExternalRepresentation(NULL
,
339 kCFStringEncodingMacRoman
,
342 pthread_mutex_lock(&lock
);
343 fprintf(stream
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
345 pthread_mutex_unlock(&lock
);
354 SCLog(Boolean condition
, int level
, CFStringRef formatString
, ...)
357 CFStringRef resultString
;
363 va_start(argList
, formatString
);
364 #ifdef USE_SCCOPYDESCRIPTION
365 resultString
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
370 #else /* USE_SCCOPYDESCRIPTION */
371 resultString
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, formatString
, argList
);
372 #endif /* !USE_SCCOPYDESCRIPTION */
376 __SCLog(level
, resultString
);
378 FILE *f
= (LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
;
379 CFStringRef newString
;
382 newString
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\n"), resultString
);
383 __SCPrint(f
, newString
);
384 CFRelease(newString
);
386 CFRelease(resultString
);
392 SCPrint(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
395 CFStringRef resultString
;
401 va_start(argList
, formatString
);
402 #ifdef USE_SCCOPYDESCRIPTION
403 resultString
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
408 #else /* USE_SCCOPYDESCRIPTION */
409 resultString
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, formatString
, argList
);
410 #endif /* !USE_SCCOPYDESCRIPTION */
413 __SCPrint(stream
, resultString
);
414 CFRelease(resultString
);
421 } __SCThreadSpecificData
, *__SCThreadSpecificDataRef
;
424 static pthread_once_t tsKeyInitialized
= PTHREAD_ONCE_INIT
;
425 static pthread_key_t tsDataKey
= NULL
;
429 __SCThreadSpecificDataFinalize(void *arg
)
431 __SCThreadSpecificDataRef tsd
= (__SCThreadSpecificDataRef
)arg
;
435 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
441 __SCThreadSpecificKeyInitialize()
443 pthread_key_create(&tsDataKey
, __SCThreadSpecificDataFinalize
);
449 _SCErrorSet(int error
)
451 __SCThreadSpecificDataRef tsd
;
453 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
455 tsd
= pthread_getspecific(tsDataKey
);
457 tsd
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__SCThreadSpecificData
), 0);
458 bzero(tsd
, sizeof(__SCThreadSpecificData
));
459 pthread_setspecific(tsDataKey
, tsd
);
462 tsd
->_sc_error
= error
;
470 __SCThreadSpecificDataRef tsd
;
472 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
474 tsd
= pthread_getspecific(tsDataKey
);
475 return tsd
? tsd
->_sc_error
: kSCStatusOK
;
480 SCErrorString(int status
)
484 for (i
= 0; i
< nSC_ERRMSGS
; i
++) {
485 if (sc_errmsgs
[i
].status
== status
) {
486 return sc_errmsgs
[i
].message
;
490 if ((status
> 0) && (status
<= ELAST
)) {
491 return strerror(status
);
494 return mach_error_string(status
);