Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
18 kB · 741 lines
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742/* * Copyright (c) 2000-2008, 2010-2019 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */
/* * Modification History * * June 1, 2001 Allan Nathanson <ajn@apple.com> * - public API conversion * * March 24, 2000 Allan Nathanson <ajn@apple.com> * - initial revision */
#include <mach/mach.h>#include <mach/mach_error.h>#include <servers/bootstrap.h>#include <pthread.h>#include <sys/time.h>#include <os/log.h>#include <os/log_private.h>
#include "SCDynamicStoreInternal.h"#include "SCD.h"#include "config.h" /* MiG generated file */
#define INSTALL_ENVIRONMENT "__OSINSTALL_ENVIRONMENT"
/* framework variables */int _sc_debug = FALSE; /* non-zero if debugging enabled */int _sc_verbose = FALSE; /* non-zero if verbose logging enabled */int _sc_log = TRUE; /* 0 if SC messages should be written to stdout/stderr, 1 if SC messages should be logged w/os_log(3), 2 if SC messages should be written to stdout/stderr AND logged */
#pragma mark -#pragma mark Thread specific data
static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT;static pthread_key_t tsDataKey;
static void__SCThreadSpecificDataFinalize(void *arg){ __SCThreadSpecificDataRef tsd = (__SCThreadSpecificDataRef)arg;
if (tsd != NULL) { if (tsd->_sc_store != NULL) CFRelease(tsd->_sc_store); CFAllocatorDeallocate(kCFAllocatorSystemDefault, tsd); } return;}
static void__SCThreadSpecificKeyInitialize(){ pthread_key_create(&tsDataKey, __SCThreadSpecificDataFinalize); return;}
__private_extern____SCThreadSpecificDataRef__SCGetThreadSpecificData(){ __SCThreadSpecificDataRef tsd; pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize);
tsd = pthread_getspecific(tsDataKey); if (tsd == NULL) { tsd = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__SCThreadSpecificData), 0); tsd->_sc_error = kSCStatusOK; tsd->_sc_store = NULL; pthread_setspecific(tsDataKey, tsd); }
return tsd;}
#pragma mark -#pragma mark Logging
#define ENABLE_SC_FORMATTING#ifdef ENABLE_SC_FORMATTING// from <CoreFoundation/ForFoundationOnly.h>extern CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(CFTypeRef, CFDictionaryRef), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);#endif /* ENABLE_SC_FORMATTING */
CFStringRef_SCCopyDescription(CFTypeRef cf, CFDictionaryRef formatOptions){#ifdef ENABLE_SC_FORMATTING CFMutableDictionaryRef nFormatOptions; CFStringRef prefix1; CFStringRef prefix2; CFTypeID type = CFGetTypeID(cf);
if (!formatOptions || !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX1"), (const void **)&prefix1)) { prefix1 = CFSTR(""); }
if (type == CFStringGetTypeID()) { return CFStringCreateWithFormat(NULL, formatOptions, CFSTR("%@%@"), prefix1, cf); }
if (type == CFBooleanGetTypeID()) { return CFStringCreateWithFormat(NULL, formatOptions, CFSTR("%@%s"), prefix1, CFBooleanGetValue(cf) ? "TRUE" : "FALSE"); }
if (type == CFDataGetTypeID()) { const uint8_t *data; CFIndex dataLen; CFIndex i; CFMutableStringRef str;
str = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(str, formatOptions, CFSTR("%@<data> 0x"), prefix1);
data = CFDataGetBytePtr(cf); dataLen = CFDataGetLength(cf); for (i = 0; i < dataLen; i++) { CFStringAppendFormat(str, NULL, CFSTR("%02x"), data[i]); }
return str; }
if (type == CFNumberGetTypeID()) { return CFStringCreateWithFormat(NULL, formatOptions, CFSTR("%@%@"), prefix1, cf); }
if (type == CFDateGetTypeID()) { CFCalendarRef calendar; CFStringRef str; CFTimeZoneRef tz; int MM, DD, YYYY, hh, mm, ss;
calendar = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar); tz = CFTimeZoneCopySystem(); CFCalendarSetTimeZone(calendar, tz); CFRelease(tz); CFCalendarDecomposeAbsoluteTime(calendar, CFDateGetAbsoluteTime(cf), "MdyHms", &MM, &DD, &YYYY, &hh, &mm, &ss); CFRelease(calendar);
str = CFStringCreateWithFormat(NULL, formatOptions, CFSTR("%@%02d/%02d/%04d %02d:%02d:%02d"), prefix1, MM, DD, YYYY, hh, mm, ss); return str; }
if ((formatOptions == NULL) || !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX2"), (const void **)&prefix2)) { prefix2 = prefix1; }
if (formatOptions != NULL) { nFormatOptions = CFDictionaryCreateMutableCopy(NULL, 0, formatOptions); } else { nFormatOptions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } assert(nFormatOptions != NULL);
#define N_QUICK 32
if (type == CFArrayGetTypeID()) { const void * elements_q[N_QUICK]; const void ** elements = elements_q; CFIndex i; CFIndex nElements; CFMutableStringRef str;
str = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(str, formatOptions, CFSTR("%@<array> {"), prefix1);
nElements = CFArrayGetCount(cf); if (nElements > 0) { if (nElements > (CFIndex)(sizeof(elements_q)/sizeof(CFTypeRef))) elements = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); CFArrayGetValues(cf, CFRangeMake(0, nElements), elements); for (i = 0; i < nElements; i++) { CFMutableStringRef nPrefix1; CFMutableStringRef nPrefix2; CFStringRef nStr; CFStringRef vStr;
nStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), i);
nPrefix1 = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(nPrefix1, formatOptions, CFSTR("%@ %@ : "), prefix2, nStr); nPrefix2 = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(nPrefix2, formatOptions, CFSTR("%@ "), prefix2);
CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX1"), nPrefix1); CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX2"), nPrefix2); CFRelease(nPrefix1); CFRelease(nPrefix2); CFRelease(nStr);
vStr = _SCCopyDescription((CFTypeRef)elements[i], nFormatOptions); CFStringAppendFormat(str, formatOptions, CFSTR("\n%@"), vStr); CFRelease(vStr); } if (elements != elements_q) CFAllocatorDeallocate(NULL, elements); } CFStringAppendFormat(str, formatOptions, CFSTR("\n%@}"), prefix2);
CFRelease(nFormatOptions); return str; }
if (type == CFDictionaryGetTypeID()) { const void * keys_q[N_QUICK]; const void ** keys = keys_q; CFIndex i; CFIndex nElements; CFMutableStringRef nPrefix1; CFMutableStringRef nPrefix2; CFMutableStringRef str;
str = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(str, formatOptions, CFSTR("%@<dictionary> {"), prefix1);
nElements = CFDictionaryGetCount(cf); if (nElements > 0) { CFComparatorFunction compFunc = NULL; CFMutableArrayRef sortedKeys;
if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(cf, keys, NULL);
sortedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); for (i = 0; i < nElements; i++) { CFArrayAppendValue(sortedKeys, (CFStringRef)keys[i]); }
if (isA_CFString(keys[0])) { compFunc = (CFComparatorFunction)CFStringCompare; } else if (isA_CFNumber(keys[0])) { compFunc = (CFComparatorFunction)CFNumberCompare; } else if (isA_CFDate(keys[0])) { compFunc = (CFComparatorFunction)CFDateCompare; }
if (compFunc != NULL) { CFArraySortValues(sortedKeys, CFRangeMake(0, nElements), compFunc, NULL); }
for (i = 0; i < nElements; i++) { CFStringRef key; CFStringRef kStr; CFTypeRef val; CFStringRef vStr;
key = CFArrayGetValueAtIndex(sortedKeys, i); kStr = _SCCopyDescription((CFTypeRef)key, NULL);
nPrefix1 = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(nPrefix1, formatOptions, CFSTR("%@ %@ : "), prefix2, kStr); nPrefix2 = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(nPrefix2, formatOptions, CFSTR("%@ "), prefix2);
CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX1"), nPrefix1); CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX2"), nPrefix2); CFRelease(nPrefix1); CFRelease(nPrefix2); CFRelease(kStr);
val = CFDictionaryGetValue(cf, key); vStr = _SCCopyDescription((CFTypeRef)val, nFormatOptions); CFStringAppendFormat(str, formatOptions, CFSTR("\n%@"), vStr); CFRelease(vStr); }
CFRelease(sortedKeys);
if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); } } CFStringAppendFormat(str, formatOptions, CFSTR("\n%@}"), prefix2);
CFRelease(nFormatOptions); return str; }
CFRelease(nFormatOptions);#endif /* ENABLE_SC_FORMATTING */
return CFStringCreateWithFormat(NULL, formatOptions, CFSTR("%@%@"), prefix1, cf);}
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Boolean_SC_isInstallEnvironment() { static dispatch_once_t once; static Boolean is_install;
dispatch_once(&once, ^{ is_install = (getenv(INSTALL_ENVIRONMENT) != NULL); });
return is_install;}
os_log_t_SC_LOG_DEFAULT(void){ static os_log_t log = NULL;
if (log == NULL) { log = os_log_create("com.apple.SystemConfiguration", ""); }
return log;}
os_log_type_t_SC_syslog_os_log_mapping(int level){ if (level < 0) { level = ~level; }
switch (level) { case LOG_EMERG : case LOG_ALERT : case LOG_CRIT : return OS_LOG_TYPE_ERROR;
case LOG_ERR : case LOG_WARNING : case LOG_NOTICE : return OS_LOG_TYPE_DEFAULT;
case LOG_INFO : return OS_LOG_TYPE_INFO;
case LOG_DEBUG : return OS_LOG_TYPE_DEBUG; }
return OS_LOG_TYPE_DEFAULT;};
static void__SCLog(void *ret_addr, os_log_type_t type, const char *formatString, va_list formatArguments){ os_log_with_args(_SC_LOG_DEFAULT(), type, formatString, formatArguments, ret_addr); return;}
static void__SCPrint(FILE *stream, CFStringRef formatString, va_list formatArguments, Boolean trace, Boolean addNL){ char *line; CFStringRef str; CFIndex usedBufLen;
#ifdef ENABLE_SC_FORMATTING str = _CFStringCreateWithFormatAndArgumentsAux(NULL, _SCCopyDescription, NULL, formatString, formatArguments);#else /* ENABLE_SC_FORMATTING */ str = CFStringCreateWithFormatAndArguments (NULL, NULL, formatString, formatArguments);#endif /* !ENABLE_SC_FORMATTING */
line =_SC_cfstring_to_cstring_ext(str, NULL, 0, kCFStringEncodingUTF8, (UInt8)'?', &usedBufLen); CFRelease(str); if (!line) { return; }
pthread_mutex_lock(&lock); if (trace) { struct tm tm_now; struct timeval tv_now;
(void)gettimeofday(&tv_now, NULL); (void)localtime_r(&tv_now.tv_sec, &tm_now); (void)fprintf(stream, "%2d:%02d:%02d.%03d ", tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec, tv_now.tv_usec / 1000); } (void)fwrite((const void *)line, usedBufLen, 1, stream); if (addNL) { (void)fputc('\n', stream); } fflush (stream); pthread_mutex_unlock(&lock); CFAllocatorDeallocate(NULL, line);
return;}
void__SC_Log(int level, CFStringRef format_CF, os_log_t log, os_log_type_t type, const char *format, ...){#pragma unused(level) Boolean do_log = FALSE; Boolean do_print = FALSE; va_list args_log; va_list args_print;
/* * Note: The following are the expected values for _sc_log * * 0 if SC messages should be written to stdout/stderr * 1 if SC messages should be logged w/os_log(3) * 2 if SC messages should be written to stdout/stderr AND logged */
if (_sc_log > 0) { do_log = TRUE; // log requested va_start(args_log, format);
if (_sc_log > 1) { do_print = TRUE; // log AND print requested va_copy(args_print, args_log); } } else { do_print = TRUE; // print requested va_start(args_print, format); }
if (do_log) { os_log_with_args(log, type, format, args_log, __builtin_return_address(0)); va_end(args_log); }
if (do_print) { __SCPrint(stdout, format_CF, args_print, (_sc_log > 0), // trace TRUE); // add newline va_end(args_print); }
return;}
voidSCLog(Boolean condition, int level, CFStringRef formatString, ...){ va_list formatArguments; va_list formatArguments_print; Boolean log = FALSE; Boolean print = FALSE;
if (!condition) { return; }
/* * Note: The following are the expected values for _sc_log * * 0 if SC messages should be written to stdout/stderr * 1 if SC messages should be logged w/os_log(3) * 2 if SC messages should be written to stdout/stderr AND logged */
if (_sc_log > 0) { log = TRUE; // log requested va_start(formatArguments, formatString);
if (_sc_log > 1) { print = TRUE; // log AND print requested va_copy(formatArguments_print, formatArguments); } } else { print = TRUE; // print requested va_start(formatArguments_print, formatString); }
if (log) { const char *__format;
__format = CFStringGetCStringPtr(formatString, kCFStringEncodingUTF8); if (__format != NULL) { os_log_type_t __type;
__type = _SC_syslog_os_log_mapping(level); __SCLog(__builtin_return_address(0), __type, __format, formatArguments); } va_end(formatArguments); }
if (print) { __SCPrint((LOG_PRI(level) > LOG_NOTICE) ? stderr : stdout, formatString, formatArguments_print, (_sc_log > 0), // trace TRUE); // add newline va_end(formatArguments_print); }
return;}
voidSCPrint(Boolean condition, FILE *stream, CFStringRef formatString, ...){ va_list formatArguments;
if (!condition) { return; }
va_start(formatArguments, formatString); __SCPrint(stream, formatString, formatArguments, FALSE, FALSE); va_end(formatArguments);
return;}
#pragma mark -#pragma mark SC error handling / logging
const CFStringRef kCFErrorDomainSystemConfiguration = CFSTR("com.apple.SystemConfiguration");
static const struct sc_errmsg { int status; char *message;} sc_errmsgs[] = { { kSCStatusAccessError, "Permission denied" }, { kSCStatusConnectionIgnore, "Network connection information not available at this time" }, { kSCStatusConnectionNoService, "Network service for connection not available" }, { kSCStatusFailed, "Failed!" }, { kSCStatusInvalidArgument, "Invalid argument" }, { kSCStatusKeyExists, "Key already defined" }, { kSCStatusLocked, "Lock already held" }, { kSCStatusMaxLink, "Maximum link count exceeded" }, { kSCStatusNeedLock, "Lock required for this operation" }, { kSCStatusNoStoreServer, "Configuration daemon not (no longer) available" }, { kSCStatusNoStoreSession, "Configuration daemon session not active" }, { kSCStatusNoConfigFile, "Configuration file not found" }, { kSCStatusNoKey, "No such key" }, { kSCStatusNoLink, "No such link" }, { kSCStatusNoPrefsSession, "Preference session not active" }, { kSCStatusNotifierActive, "Notifier is currently active" }, { kSCStatusOK, "Success!" }, { kSCStatusPrefsBusy, "Preferences update currently in progress" }, { kSCStatusReachabilityUnknown, "Network reachability cannot be determined" }, { kSCStatusStale, "Write attempted on stale version of object" },};#define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
void_SCErrorSet(int error){ __SCThreadSpecificDataRef tsd;
tsd = __SCGetThreadSpecificData(); tsd->_sc_error = error; return;}
CFErrorRefSCCopyLastError(void){ CFStringRef domain; CFErrorRef error; int i; int code; __SCThreadSpecificDataRef tsd; CFMutableDictionaryRef userInfo = NULL;
tsd = __SCGetThreadSpecificData(); code =tsd->_sc_error;
for (i = 0; i < (int)nSC_ERRMSGS; i++) { if (sc_errmsgs[i].status == code) { CFStringRef str;
domain = kCFErrorDomainSystemConfiguration; userInfo = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); str = CFStringCreateWithCString(NULL, sc_errmsgs[i].message, kCFStringEncodingASCII); CFDictionarySetValue(userInfo, kCFErrorDescriptionKey, str); CFRelease(str); goto done; } }
if ((code > 0) && (code <= ELAST)) { domain = kCFErrorDomainPOSIX; goto done; }
domain = kCFErrorDomainMach;
done :
error = CFErrorCreate(NULL, domain, code, userInfo); if (userInfo != NULL) CFRelease(userInfo); return error;}
intSCError(void){ __SCThreadSpecificDataRef tsd;
tsd = __SCGetThreadSpecificData(); return tsd->_sc_error;}
const char *SCErrorString(int status){ int i;
for (i = 0; i < (int)nSC_ERRMSGS; i++) { if (sc_errmsgs[i].status == status) { return sc_errmsgs[i].message; } }
if ((status > 0) && (status <= ELAST)) { return strerror(status); }
if ((status >= BOOTSTRAP_SUCCESS) && (status <= BOOTSTRAP_NO_MEMORY)) { return bootstrap_strerror(status); }
return mach_error_string(status);}