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>
36 #include <mach/mach.h>
37 #include <mach/mach_error.h>
40 #include <SystemConfiguration/SystemConfiguration.h>
41 #include <SystemConfiguration/SCPrivate.h>
42 #include "SCDynamicStoreInternal.h"
43 #include "config.h" /* MiG generated file */
45 /* framework variables */
46 Boolean _sc_debug
= FALSE
; /* TRUE if debugging enabled */
47 Boolean _sc_verbose
= FALSE
; /* TRUE if verbose logging enabled */
48 Boolean _sc_log
= TRUE
; /* TRUE if SCLog() output goes to syslog */
50 static const struct sc_errmsg
{
54 { kSCStatusAccessError
, "Permission denied" },
55 { kSCStatusFailed
, "Failed!" },
56 { kSCStatusInvalidArgument
, "Invalid argument" },
57 { kSCStatusKeyExists
, "Key already defined" },
58 { kSCStatusLocked
, "Lock already held" },
59 { kSCStatusMaxLink
, "Maximum link count exceeded" },
60 { kSCStatusNeedLock
, "Lock required for this operation" },
61 { kSCStatusNoStoreServer
, "Configuration daemon not (no longer) available" },
62 { kSCStatusNoStoreSession
, "Configuration daemon session not active" },
63 { kSCStatusNoConfigFile
, "Configuration file not found" },
64 { kSCStatusNoKey
, "No such key" },
65 { kSCStatusNoLink
, "No such link" },
66 { kSCStatusNoPrefsSession
, "Preference session not active" },
67 { kSCStatusNotifierActive
, "Notifier is currently active" },
68 { kSCStatusOK
, "Success!" },
69 { kSCStatusPrefsBusy
, "Configuration daemon busy" },
70 { kSCStatusReachabilityUnknown
, "Network reachability cannot be determined" },
71 { kSCStatusStale
, "Write attempted on stale version of object" },
73 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
76 #define USE_SCCOPYDESCRIPTION
77 #ifdef USE_SCCOPYDESCRIPTION
79 // from <CoreFoundation/CFVeryPrivate.h>
80 extern CFStringRef
_CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc
, CFStringRef (*copyDescFunc
)(void *, CFDictionaryRef
), CFDictionaryRef formatOptions
, CFStringRef format
, va_list arguments
);
85 _SCCopyDescription(void *info
, CFDictionaryRef formatOptions
)
87 CFMutableDictionaryRef nFormatOptions
;
90 CFTypeID type
= CFGetTypeID(info
);
93 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX1"), (const void **)&prefix1
)) {
97 if (type
== CFStringGetTypeID()) {
98 return CFStringCreateWithFormat(NULL
,
105 if (type
== CFBooleanGetTypeID()) {
106 return CFStringCreateWithFormat(NULL
,
110 CFBooleanGetValue(info
) ? "TRUE" : "FALSE");
113 if (type
== CFDataGetTypeID()) {
117 CFMutableStringRef str
;
119 str
= CFStringCreateMutable(NULL
, 0);
120 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<data> 0x"), prefix1
);
122 data
= CFDataGetBytePtr(info
);
123 dataLen
= CFDataGetLength(info
);
124 for (i
= 0; i
< dataLen
; i
++) {
125 CFStringAppendFormat(str
, NULL
, CFSTR("%02x"), data
[i
]);
131 if (type
== CFNumberGetTypeID()) {
132 return CFStringCreateWithFormat(NULL
,
139 if (type
== CFDateGetTypeID()) {
140 CFGregorianDate gDate
;
144 tZone
= CFTimeZoneCopySystem();
145 gDate
= CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(info
), tZone
);
146 str
= CFStringCreateWithFormat(NULL
,
148 CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
156 CFTimeZoneGetName(tZone
));
161 if (!formatOptions
||
162 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX2"), (const void **)&prefix2
)) {
163 prefix2
= CFStringCreateCopy(NULL
, prefix1
);
167 nFormatOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, formatOptions
);
169 nFormatOptions
= CFDictionaryCreateMutable(NULL
,
171 &kCFTypeDictionaryKeyCallBacks
,
172 &kCFTypeDictionaryValueCallBacks
);
175 if (type
== CFArrayGetTypeID()) {
176 const void * elements_q
[32];
177 const void ** elements
= elements_q
;
180 CFMutableStringRef str
;
182 str
= CFStringCreateMutable(NULL
, 0);
183 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<array> {"), prefix1
);
185 nElements
= CFArrayGetCount(info
);
187 if (nElements
> (CFIndex
)(sizeof(elements_q
)/sizeof(CFTypeRef
)))
188 elements
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
189 CFArrayGetValues(info
, CFRangeMake(0, nElements
), elements
);
190 for (i
= 0; i
< nElements
; i
++) {
191 CFMutableStringRef nPrefix1
;
192 CFMutableStringRef nPrefix2
;
196 nStr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%u"), i
);
198 nPrefix1
= CFStringCreateMutable(NULL
, 0);
199 CFStringAppendFormat(nPrefix1
,
204 nPrefix2
= CFStringCreateMutable(NULL
, 0);
205 CFStringAppendFormat(nPrefix2
,
210 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
211 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
216 vStr
= _SCCopyDescription((void *)elements
[i
], nFormatOptions
);
217 CFStringAppendFormat(str
,
223 if (elements
!= elements_q
) CFAllocatorDeallocate(NULL
, elements
);
225 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
227 CFRelease(nFormatOptions
);
231 if (type
== CFDictionaryGetTypeID()) {
232 const void * keys_q
[N_QUICK
];
233 const void ** keys
= keys_q
;
236 CFMutableStringRef nPrefix1
;
237 CFMutableStringRef nPrefix2
;
238 CFMutableStringRef str
;
239 const void * values_q
[N_QUICK
];
240 const void ** values
= values_q
;
242 str
= CFStringCreateMutable(NULL
, 0);
243 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<dictionary> {"), prefix1
);
245 nElements
= CFDictionaryGetCount(info
);
247 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
248 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
249 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
251 CFDictionaryGetKeysAndValues(info
, keys
, values
);
252 for (i
= 0; i
< nElements
; i
++) {
256 kStr
= _SCCopyDescription((void *)keys
[i
], NULL
);
258 nPrefix1
= CFStringCreateMutable(NULL
, 0);
259 CFStringAppendFormat(nPrefix1
,
264 nPrefix2
= CFStringCreateMutable(NULL
, 0);
265 CFStringAppendFormat(nPrefix2
,
270 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
271 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
276 vStr
= _SCCopyDescription((void *)values
[i
], nFormatOptions
);
277 CFStringAppendFormat(str
,
283 if (keys
!= keys_q
) {
284 CFAllocatorDeallocate(NULL
, keys
);
285 CFAllocatorDeallocate(NULL
, values
);
288 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
290 CFRelease(nFormatOptions
);
294 CFRelease(nFormatOptions
);
300 cfStr
= CFCopyDescription(info
);
301 str
= CFStringCreateWithFormat(NULL
,
311 #endif /* USE_SCCOPYDESCRIPTION */
314 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
318 __SCLog(int level
, CFStringRef formatString
, va_list formatArguments
)
323 #ifdef USE_SCCOPYDESCRIPTION
324 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
329 #else /* USE_SCCOPYDESCRIPTION */
330 str
= CFStringCreateWithFormatAndArguments (NULL
,
334 #endif /* !USE_SCCOPYDESCRIPTION */
336 lines
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR("\n"));
341 int n
= CFArrayGetCount(lines
);
343 pthread_mutex_lock(&lock
);
344 for (i
= 0; i
< n
; i
++) {
347 line
= CFStringCreateExternalRepresentation(NULL
,
348 CFArrayGetValueAtIndex(lines
, i
),
349 kCFStringEncodingMacRoman
,
352 syslog (level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
356 pthread_mutex_unlock(&lock
);
365 __SCPrint(FILE *stream
, CFStringRef formatString
, va_list formatArguments
, Boolean trace
, Boolean addNL
)
370 #ifdef USE_SCCOPYDESCRIPTION
371 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
376 #else /* USE_SCCOPYDESCRIPTION */
377 str
= CFStringCreateWithFormatAndArguments (NULL
,
381 #endif /* !USE_SCCOPYDESCRIPTION */
383 line
= CFStringCreateExternalRepresentation(NULL
,
385 kCFStringEncodingMacRoman
,
392 pthread_mutex_lock(&lock
);
394 time_t now
= time(NULL
);
397 (void)localtime_r(&now
, &tm
);
398 fprintf(stream
, "%2d:%02d:%02d %.*s%s",
399 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
,
400 (int)CFDataGetLength(line
), CFDataGetBytePtr(line
),
403 fprintf(stream
, "%.*s%s",
404 (int)CFDataGetLength(line
), CFDataGetBytePtr(line
),
408 pthread_mutex_unlock(&lock
);
416 SCLog(Boolean condition
, int level
, CFStringRef formatString
, ...)
418 va_list formatArguments
;
424 va_start(formatArguments
, formatString
);
426 __SCLog(level
, formatString
, formatArguments
);
428 __SCPrint((LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
,
432 TRUE
); // add newline
434 va_end(formatArguments
);
441 SCPrint(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
443 va_list formatArguments
;
449 va_start(formatArguments
, formatString
);
450 __SCPrint(stream
, formatString
, formatArguments
, FALSE
, FALSE
);
451 va_end(formatArguments
);
458 SCTrace(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
460 va_list formatArguments
;
466 va_start(formatArguments
, formatString
);
467 __SCPrint(stream
, formatString
, formatArguments
, TRUE
, FALSE
);
468 va_end(formatArguments
);
476 } __SCThreadSpecificData
, *__SCThreadSpecificDataRef
;
479 static pthread_once_t tsKeyInitialized
= PTHREAD_ONCE_INIT
;
480 static pthread_key_t tsDataKey
= NULL
;
484 __SCThreadSpecificDataFinalize(void *arg
)
486 __SCThreadSpecificDataRef tsd
= (__SCThreadSpecificDataRef
)arg
;
490 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
496 __SCThreadSpecificKeyInitialize()
498 pthread_key_create(&tsDataKey
, __SCThreadSpecificDataFinalize
);
504 _SCErrorSet(int error
)
506 __SCThreadSpecificDataRef tsd
;
508 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
510 tsd
= pthread_getspecific(tsDataKey
);
512 tsd
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__SCThreadSpecificData
), 0);
513 bzero(tsd
, sizeof(__SCThreadSpecificData
));
514 pthread_setspecific(tsDataKey
, tsd
);
517 tsd
->_sc_error
= error
;
525 __SCThreadSpecificDataRef tsd
;
527 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
529 tsd
= pthread_getspecific(tsDataKey
);
530 return tsd
? tsd
->_sc_error
: kSCStatusOK
;
535 SCErrorString(int status
)
539 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
540 if (sc_errmsgs
[i
].status
== status
) {
541 return sc_errmsgs
[i
].message
;
545 if ((status
> 0) && (status
<= ELAST
)) {
546 return strerror(status
);
549 return mach_error_string(status
);