Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, UInt32 len, CFStringEncoding encoding, Boolean alwaysUnicode, CFVarWidthCharBuffer *buffer, Boolean *useClientsMemoryPtr, UInt32 converterFlags) { UInt32 idx; const UniChar *uniChars = (const UniChar *)bytes; const uint8_t *chars = (const uint8_t *)bytes; const uint8_t *end = chars + len; uint16_t bom; Boolean allASCII = false; if (useClientsMemoryPtr) *useClientsMemoryPtr = false; buffer->isASCII = !alwaysUnicode; buffer->shouldFreeChars = false; buffer->numChars = 0; if (0 == len) return true; buffer->allocator = (buffer->allocator ? buffer->allocator : __CFGetDefaultAllocator()); switch (encoding) { case kCFStringEncodingUnicode: bom = (*uniChars == 0xfffe || *uniChars == 0xfeff) ? (*uniChars++) : 0; /* If the byte order mark is missing, we assume big endian... */ len = len / 2 - (0 == bom ? 0 : 1); if (buffer->isASCII) { // Let's see if we can reduce the Unicode down to ASCII... if (SHOULD_SWAP(bom)) { for (idx = 0; idx < len; idx++) if ((uniChars[idx] & 0x80ff) != 0) {buffer->isASCII = false; break;} } else { for (idx = 0; idx < len; idx++) if (uniChars[idx] > 127) {buffer->isASCII = false; break;} } } if (buffer->isASCII) { buffer->numChars = len; buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true; buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0)); if (SHOULD_SWAP(bom)) { // !!! Can be somewhat trickier here and use a single loop with a properly inited ptr for (idx = 0; idx < len; idx++) buffer->chars.ascii[idx] = (uniChars[idx] >> 8); } else { for (idx = 0; idx < len; idx++) buffer->chars.ascii[idx] = uniChars[idx]; } } else {
inline void *__JSONAllocatorAllocate(void *ctx, size_t sz) { return CFAllocatorAllocate(ctx, sz, 0); }
static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) { struct __CFAllocator *memory = NULL; CFAllocatorRetainCallBack retainFunc; CFAllocatorAllocateCallBack allocateFunc; void *retainedInfo; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI if (allocator && kCFAllocatorUseContext != allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t * return NULL; // require allocator to this function to be an allocator } #endif retainFunc = context->retain; FAULT_CALLBACK((void **)&retainFunc); allocateFunc = context->allocate; FAULT_CALLBACK((void **)&allocateFunc); if (NULL != retainFunc) { retainedInfo = (void *)INVOKE_CALLBACK1(retainFunc, context->info); } else { retainedInfo = context->info; } // We don't use _CFRuntimeCreateInstance() if (kCFAllocatorUseContext == allocator) { memory = NULL; if (allocateFunc) { memory = (struct __CFAllocator *)INVOKE_CALLBACK3(allocateFunc, sizeof(struct __CFAllocator), 0, retainedInfo); } if (NULL == memory) { return NULL; } } else { allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator; memory = (struct __CFAllocator *)CFAllocatorAllocate(allocator, sizeof(struct __CFAllocator), __kCFAllocatorGCObjectMemory); if (NULL == memory) { return NULL; } if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFAllocator"); } memset(memory, 0, sizeof(CFRuntimeBase)); memory->_base._cfisa = 0; #if __LP64__ memory->_base._rc = 1; #else memory->_base._cfinfo[CF_RC_BITS] = 1; #endif memory->_base._cfinfo[CF_INFO_BITS] = 0; _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID); memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI memory->size = __CFAllocatorCustomSize; memory->malloc = __CFAllocatorCustomMalloc; memory->calloc = __CFAllocatorCustomCalloc; memory->valloc = __CFAllocatorCustomValloc; memory->free = __CFAllocatorCustomFree; memory->realloc = __CFAllocatorCustomRealloc; memory->destroy = __CFAllocatorCustomDestroy; memory->zone_name = "Custom CFAllocator"; memory->batch_malloc = NULL; memory->batch_free = NULL; memory->introspect = &__CFAllocatorZoneIntrospect; memory->version = 6; memory->memalign = NULL; memory->free_definite_size = NULL; #endif memory->_allocator = allocator; memory->_context.version = context->version; memory->_context.info = retainedInfo; memory->_context.retain = retainFunc; memory->_context.release = context->release; FAULT_CALLBACK((void **)&(memory->_context.release)); memory->_context.copyDescription = context->copyDescription; FAULT_CALLBACK((void **)&(memory->_context.copyDescription)); memory->_context.allocate = allocateFunc; memory->_context.reallocate = context->reallocate; FAULT_CALLBACK((void **)&(memory->_context.reallocate)); memory->_context.deallocate = context->deallocate; FAULT_CALLBACK((void **)&(memory->_context.deallocate)); memory->_context.preferredSize = context->preferredSize; FAULT_CALLBACK((void **)&(memory->_context.preferredSize)); return memory; }
__private_extern__ CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); CFArrayRef domains; CFMutableArrayRef marray; CFStringRef *cachedDomainKeys; CFPreferencesDomainRef *cachedDomains; SInt32 idx, cnt; CFStringRef suffix; UInt32 suffixLen; CFURLRef prefDir = _preferencesDirectoryForUserHost(userName, hostName); if (!prefDir) { return NULL; } if (hostName == kCFPreferencesAnyHost) { suffix = CFStringCreateWithCString(prefAlloc, ".plist", kCFStringEncodingASCII); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostID); } else { suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostName); // sketchy - this allows someone to create a domain list for an arbitrary hostname. } suffixLen = CFStringGetLength(suffix); domains = (CFArrayRef)CFURLCreatePropertyFromResource(prefAlloc, prefDir, kCFURLFileDirectoryContents, NULL); CFRelease(prefDir); if (domains){ marray = CFArrayCreateMutableCopy(prefAlloc, 0, domains); CFRelease(domains); } else { marray = CFArrayCreateMutable(prefAlloc, 0, & kCFTypeArrayCallBacks); } for (idx = CFArrayGetCount(marray)-1; idx >= 0; idx --) { CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(marray, idx); CFStringRef string = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); if (!CFStringHasSuffix(string, suffix)) { CFArrayRemoveValueAtIndex(marray, idx); } else { CFStringRef dom = CFStringCreateWithSubstring(prefAlloc, string, CFRangeMake(0, CFStringGetLength(string) - suffixLen)); if (CFEqual(dom, CFSTR(".GlobalPreferences"))) { CFArraySetValueAtIndex(marray, idx, kCFPreferencesAnyApplication); } else { CFArraySetValueAtIndex(marray, idx, dom); } CFRelease(dom); } CFRelease(string); } CFRelease(suffix); // Now add any domains added in the cache; delete any that have been deleted in the cache __CFSpinLock(&domainCacheLock); if (!domainCache) { __CFSpinUnlock(&domainCacheLock); return marray; } cnt = CFDictionaryGetCount(domainCache); cachedDomainKeys = (CFStringRef *)CFAllocatorAllocate(prefAlloc, 2 * cnt * sizeof(CFStringRef), 0); cachedDomains = (CFPreferencesDomainRef *)(cachedDomainKeys + cnt); CFDictionaryGetKeysAndValues(domainCache, (const void **)cachedDomainKeys, (const void **)cachedDomains); __CFSpinUnlock(&domainCacheLock); suffix = _CFPreferencesCachePrefixForUserHost(userName, hostName); suffixLen = CFStringGetLength(suffix); for (idx = 0; idx < cnt; idx ++) { CFStringRef domainKey = cachedDomainKeys[idx]; CFPreferencesDomainRef domain = cachedDomains[idx]; CFStringRef domainName; CFIndex keyCount = 0; if (!CFStringHasPrefix(domainKey, suffix)) continue; domainName = CFStringCreateWithSubstring(prefAlloc, domainKey, CFRangeMake(suffixLen, CFStringGetLength(domainKey) - suffixLen)); if (CFEqual(domainName, CFSTR("*"))) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(kCFPreferencesAnyApplication); } else if (CFEqual(domainName, kCFPreferencesCurrentApplication)) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(_CFProcessNameString()); } CFDictionaryRef d = _CFPreferencesDomainDeepCopyDictionary(domain); keyCount = d ? CFDictionaryGetCount(d) : 0; if (keyCount) CFRelease(d); if (keyCount == 0) { // Domain was deleted SInt32 firstIndexOfValue = CFArrayGetFirstIndexOfValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName); if (0 <= firstIndexOfValue) { CFArrayRemoveValueAtIndex(marray, firstIndexOfValue); } } else if (!CFArrayContainsValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName)) { CFArrayAppendValue(marray, domainName); } CFRelease(domainName); } CFRelease(suffix); CFAllocatorDeallocate(prefAlloc, cachedDomainKeys); return marray; }
static int PPPExec(int ref, u_int8_t *serviceid, u_int32_t cmd, void *request, u_int32_t requestLen, void **reply, u_int32_t *replyLen) { struct ppp_msg_hdr msg; char *buf = NULL; ssize_t n; bzero(&msg, sizeof(msg)); if (serviceid) { // serviceid is present, use it msg.m_flags = USE_SERVICEID; msg.m_link = strlen(serviceid); } else { // no service ID, use the default link msg.m_link = -1; } msg.m_type = cmd; msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0; // send the command if (writen(ref, &msg, sizeof(msg)) < 0) { fprintf(stderr, "PPPExec write() failed: %s\n", strerror(errno)); return errno; } if (serviceid) { if (writen(ref, serviceid, msg.m_link) < 0) { fprintf(stderr, "PPPExec write() failed: %s\n", strerror(errno)); return errno; } } if ((request != NULL) && (requestLen > 0)) { if (writen(ref, request, requestLen) < 0) { fprintf(stderr, "PPPExec write() failed: %s\n", strerror(errno)); return errno; } } // always expect a reply n = readn(ref, &msg, sizeof(msg)); if (n == -1) { fprintf(stderr, "PPPExec read() failed: error=%s\n", strerror(errno)); return errno; } else if (n != sizeof(msg)) { fprintf(stderr, "PPPExec read() failed: insufficent data, read=%d\n", n); return -1; } if (serviceid && msg.m_link) { buf = CFAllocatorAllocate(NULL, msg.m_link, 0); if (buf) { // read reply n = readn(ref, buf, msg.m_link); if (n == -1) { fprintf(stderr, "PPPExec read() failed: error=%s\n", strerror(errno)); CFAllocatorDeallocate(NULL, buf); return errno; } else if (n != msg.m_link) { fprintf(stderr, "PPPExec read() failed: insufficent data, read=%d\n", n); CFAllocatorDeallocate(NULL, buf); return -1; } // buf contains the service id we passed in the request CFAllocatorDeallocate(NULL, buf); buf = NULL; } } if (msg.m_len) { buf = CFAllocatorAllocate(NULL, msg.m_len, 0); if (buf) { // read reply n = readn(ref, buf, msg.m_len); if (n == -1) { fprintf(stderr, "PPPExec read() failed: error=%s\n", strerror(errno)); CFAllocatorDeallocate(NULL, buf); return errno; } else if (n != msg.m_len) { fprintf(stderr, "PPPExec read() failed: insufficent data, read=%d\n", n); CFAllocatorDeallocate(NULL, buf); return -1; } } } if (reply && replyLen) { *reply = buf; *replyLen = msg.m_len; } else if (buf) { // if additional returned data is unwanted CFAllocatorDeallocate(NULL, buf); } return msg.m_result; }
int main(int argc, char **argv) { const char *command = argv[0]; extern int optind; int opt; CFStringRef current = NULL; int currentMatched = 0; CFStringRef newSet = NULL; /* set key */ CFStringRef newSetUDN = NULL; /* user defined name */ CFStringRef prefix; SCPreferencesRef prefs; CFDictionaryRef sets; CFIndex nSets; const void **setKeys = NULL; const void **setVals = NULL; CFIndex i; #if !TARGET_OS_IPHONE AuthorizationRef authorization = NULL; AuthorizationFlags flags = kAuthorizationFlagDefaults; CFMutableDictionaryRef options; OSStatus status; #endif // !TARGET_OS_IPHONE /* process any arguments */ while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) { switch(opt) { case 'd': _sc_debug = TRUE; _sc_log = FALSE; /* enable framework logging */ break; case 'v': _sc_verbose = TRUE; break; case 'n': apply = FALSE; break; case '?': default : usage(command); } } argc -= optind; argv += optind; prefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/"), kSCPrefSets); if (argc == 1) { newSet = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); /* check if a full path to the new "set" was specified */ if ((CFStringGetLength(newSet) > 0) && CFStringHasPrefix(newSet, prefix)) { CFRange range; CFMutableStringRef str; str = CFStringCreateMutableCopy(NULL, 0, newSet); CFRelease(newSet); CFStringDelete(str, CFRangeMake(0, CFStringGetLength(prefix))); newSet = CFStringCreateCopy(NULL, newSet); CFRelease(str); range = CFStringFind(newSet, CFSTR("/"), 0); if (range.location != kCFNotFound) { SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n."), newSet); exit (1); } } } else { newSet = CFRetain(CFSTR("")); } #if !TARGET_OS_IPHONE status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, flags, &authorization); if (status != errAuthorizationSuccess) { SCPrint(TRUE, stderr, CFSTR("AuthorizationCreate() failed: status = %d\n"), (int)status); exit (1); } options = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(options, kSCPreferencesOptionChangeNetworkSet, kCFBooleanTrue); prefs = SCPreferencesCreateWithOptions(NULL, CFSTR("scselect"), NULL, authorization, options); CFRelease(options); if (prefs == NULL) { SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n")); exit (1); } #else // !TARGET_OS_IPHONE prefs = SCPreferencesCreate(NULL, CFSTR("scselect"), NULL); if (prefs == NULL) { SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n")); exit (1); } #endif // !TARGET_OS_IPHONE sets = SCPreferencesGetValue(prefs, kSCPrefSets); if (sets == NULL) { SCPrint(TRUE, stderr, CFSTR("No network sets defined.\n")); exit (1); } current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet); if (current != NULL) { if (CFStringHasPrefix(current, prefix)) { CFMutableStringRef tmp; tmp = CFStringCreateMutableCopy(NULL, 0, current); CFStringDelete(tmp, CFRangeMake(0, CFStringGetLength(prefix))); current = tmp; } else { CFRetain(current); currentMatched = -1; /* not prefixed */ } } else { current = CFRetain(CFSTR("")); currentMatched = -2; /* not defined */ } nSets = CFDictionaryGetCount(sets); if (nSets > 0) { setKeys = CFAllocatorAllocate(NULL, nSets * sizeof(CFStringRef), 0); setVals = CFAllocatorAllocate(NULL, nSets * sizeof(CFDictionaryRef), 0); CFDictionaryGetKeysAndValues(sets, setKeys, setVals); } /* check for set with matching name */ for (i = 0; i < nSets; i++) { CFStringRef key = (CFStringRef) setKeys[i]; CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; if ((currentMatched >= 0) && CFEqual(key, current)) { currentMatched++; } if (CFEqual(newSet, key)) { newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName); if (newSetUDN != NULL) CFRetain(newSetUDN); goto found; } } /* check for set with matching user-defined name */ for (i = 0; i < nSets; i++) { CFStringRef key = (CFStringRef) setKeys[i]; CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName); if ((newSetUDN != NULL) && CFEqual(newSet, newSetUDN)) { CFRelease(newSet); newSet = CFRetain(key); CFRetain(newSetUDN); goto found; } } if (argc == 1) { SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available.\n"), newSet); exit(1); } SCPrint(TRUE, stdout, CFSTR("Defined sets include:%s\n"), (currentMatched > 0) ? " (* == current set)" : ""); for (i = 0; i < nSets; i++) { CFStringRef key = (CFStringRef) setKeys[i]; CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; CFStringRef udn = CFDictionaryGetValue(dict, kSCPropUserDefinedName); SCPrint(TRUE, stdout, CFSTR(" %s %@\t(%@)\n"), ((currentMatched > 0) && CFEqual(key, current)) ? "*" : " ", key, udn ? udn : CFSTR("")); } switch (currentMatched) { case -2 : SCPrint(TRUE, stdout, CFSTR("\nCurrent set not defined.\n")); break; case -1 : SCPrint(TRUE, stdout, CFSTR("\nCurrent set \"%@\" may not be valid\n"), current); break; case 0 : SCPrint(TRUE, stdout, CFSTR("\nCurrent set \"%@\" not valid\n"), current); break; default : break; } CFRelease(prefix); exit (0); found : CFRelease(current); current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet); if (!SCPreferencesSetValue(prefs, kSCPrefCurrentSet, current)) { SCPrint(TRUE, stderr, CFSTR("SCPreferencesSetValue(...,%@,%@) failed: %s\n"), kSCPrefCurrentSet, current, SCErrorString(SCError())); exit (1); } if (!SCPreferencesCommitChanges(prefs)) { int sc_status = SCError(); if (sc_status == kSCStatusAccessError) { SCPrint(TRUE, stderr, CFSTR("Only local console users and administrators can change locations\n")); exit (EX_NOPERM); } else { SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed: %s\n"), SCErrorString(sc_status)); exit (1); } } if (apply) { if (!SCPreferencesApplyChanges(prefs)) { SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed %s\n"), SCErrorString(SCError())); exit (1); } } SCPrint(TRUE, stdout, CFSTR("%@ updated to %@ (%@)\n"), kSCPrefCurrentSet, newSet, newSetUDN ? newSetUDN : CFSTR("")); CFRelease(current); CFRelease(newSet); if (newSetUDN != NULL) CFRelease(newSetUDN); CFRelease(prefix); CFRelease(prefs); #if !TARGET_OS_IPHONE AuthorizationFree(authorization, kAuthorizationFlagDefaults); // AuthorizationFree(authorization, kAuthorizationFlagDestroyRights); #endif /* !TARGET_OS_IPHONE */ exit (0); return 0; }
// may move deque storage, as it may need to grow deque static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange range, CFIndex newCount) { // newCount elements are going to replace the range, and the result will fit in the deque struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store; struct __CFArrayBucket *buckets; CFIndex cnt, futureCnt, numNewElems; CFIndex L, A, B, C, R; buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque)); cnt = __CFArrayGetCount(array); futureCnt = cnt - range.length + newCount; L = deque->_leftIdx; // length of region to left of deque A = range.location; // length of region in deque to left of replaced range B = range.length; // length of replaced range C = cnt - B - A; // length of region in deque to right of replaced range R = deque->_capacity - cnt - L; // length of region to right of deque numNewElems = newCount - B; CFIndex wiggle = deque->_capacity >> 17; if (wiggle < 4) wiggle = 4; if (deque->_capacity < (uint32_t)futureCnt || (cnt < futureCnt && L + R < wiggle)) { // must be inserting or space is tight, reallocate and re-center everything CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt + wiggle); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); CFAllocatorRef allocator = __CFGetAllocator(array); allocator = _CFConvertAllocatorToGCRefZeroEquivalent(allocator); Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator); struct __CFArrayDeque *newDeque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (__CFOASafe) __CFSetLastAllocationEventName(newDeque, "CFArray (store-deque)"); struct __CFArrayBucket *newBuckets = (struct __CFArrayBucket *)((uint8_t *)newDeque + sizeof(struct __CFArrayDeque)); CFIndex oldL = L; CFIndex newL = (capacity - futureCnt) / 2; CFIndex oldC0 = oldL + A + B; CFIndex newC0 = newL + A + newCount; newDeque->_leftIdx = newL; newDeque->_capacity = capacity; if (0 < A) objc_memmove_collectable(newBuckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket)); if (0 < C) objc_memmove_collectable(newBuckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket)); __CFAssignWithWriteBarrier((void **)&array->_store, (void *)newDeque); if (!collectableMemory && deque) CFAllocatorDeallocate(allocator, deque); //printf("3: array %p store is now %p (%lx)\n", array, array->_store, *(unsigned long *)(array->_store)); return; } if ((numNewElems < 0 && C < A) || (numNewElems <= R && C < A)) { // move C // deleting: C is smaller // inserting: C is smaller and R has room CFIndex oldC0 = L + A + B; CFIndex newC0 = L + A + newCount; if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket)); // GrP GC: zero-out newly exposed space on the right, if any if (oldC0 > newC0) memset(buckets + newC0 + C, 0, (oldC0 - newC0) * sizeof(struct __CFArrayBucket)); } else if ((numNewElems < 0) || (numNewElems <= L && A <= C)) { // move A // deleting: A is smaller or equal (covers remaining delete cases) // inserting: A is smaller and L has room CFIndex oldL = L; CFIndex newL = L - numNewElems; deque->_leftIdx = newL; if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket)); // GrP GC: zero-out newly exposed space on the left, if any if (newL > oldL) memset(buckets + oldL, 0, (newL - oldL) * sizeof(struct __CFArrayBucket)); } else { // now, must be inserting, and either: // A<=C, but L doesn't have room (R might have, but don't care) // C<A, but R doesn't have room (L might have, but don't care) // re-center everything CFIndex oldL = L; CFIndex newL = (L + R - numNewElems) / 2; newL = newL - newL / 2; CFIndex oldC0 = oldL + A + B; CFIndex newC0 = newL + A + newCount; deque->_leftIdx = newL; if (newL < oldL) { if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket)); if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket)); // GrP GC: zero-out newly exposed space on the right, if any if (oldC0 > newC0) memset(buckets + newC0 + C, 0, (oldC0 - newC0) * sizeof(struct __CFArrayBucket)); } else { if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket)); if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket)); // GrP GC: zero-out newly exposed space on the left, if any if (newL > oldL) memset(buckets + oldL, 0, (newL - oldL) * sizeof(struct __CFArrayBucket)); } } }
//------------------------------------------------------------------------------ // __IOMIGMachPortPortCallback //------------------------------------------------------------------------------ void __IOMIGMachPortPortCallback(CFMachPortRef port __unused, void *msg, CFIndex size __unused, void *info) { IOMIGMachPortRef migPort = (IOMIGMachPortRef)info; mig_reply_error_t * bufRequest = msg; mig_reply_error_t * bufReply = NULL; mach_msg_return_t mr; int options; require(migPort, exit); CFRetain(migPort); bufReply = CFAllocatorAllocate(NULL, migPort->maxMessageSize, 0); require(bufReply, exit); // let's see if we have no more senders if ( __NoMoreSenders(&bufRequest->Head, &bufReply->Head) ) { if ( migPort->terminationCallback ) (*migPort->terminationCallback)(migPort, migPort->terminationRefcon); else { goto exit; } } else { if ( migPort->demuxCallback ) (*migPort->demuxCallback)(migPort, &bufRequest->Head, &bufReply->Head, migPort->demuxRefcon); else { mach_msg_destroy(&bufRequest->Head); goto exit; } } if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (bufReply->RetCode != KERN_SUCCESS)) { //This return code is a little tricky -- it appears that the //demux routine found an error of some sort, but since that //error would not normally get returned either to the local //user or the remote one, we pretend it's ok. require(bufReply->RetCode != MIG_NO_REPLY, exit); // destroy any out-of-line data in the request buffer but don't destroy // the reply port right (since we need that to send an error message). bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; mach_msg_destroy(&bufRequest->Head); } if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) { //no reply port, so destroy the reply if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { mach_msg_destroy(&bufReply->Head); } goto exit; } // send reply. // We don't want to block indefinitely because the migPort // isn't receiving messages from the reply port. // If we have a send-once right for the reply port, then // this isn't a concern because the send won't block. // If we have a send right, we need to use MACH_SEND_TIMEOUT. // To avoid falling off the kernel's fast RPC path unnecessarily, // we only supply MACH_SEND_TIMEOUT when absolutely necessary. options = MACH_SEND_MSG; if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) { options |= MACH_SEND_TIMEOUT; } mr = mach_msg(&bufReply->Head, options, bufReply->Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); // Has a message error occurred? switch (mr) { case MACH_SEND_INVALID_DEST: case MACH_SEND_TIMED_OUT: // the reply can't be delivered, so destroy it mach_msg_destroy(&bufReply->Head); break; default : // Includes success case. break; } exit: if ( bufReply ) CFAllocatorDeallocate(NULL, bufReply); if ( migPort ) CFRelease(migPort); }
/* extern */ HttpContextRef HttpContextCreate(CFAllocatorRef alloc, CFSocketNativeHandle nativeSocket) { HttpContextRef context = NULL; do { // Allocate the buffer for the context. context = CFAllocatorAllocate(alloc, sizeof(context[0]), 0); // Fail if unable to create the context if (context == NULL) break; memset(context, 0, sizeof(context[0])); // Save the allocator for deallocating later. if (alloc) context->_alloc = CFRetain(alloc); // Bump the retain count. HttpContextRetain(context); // Create the streams for the incoming socket connection. CFStreamCreatePairWithSocket(alloc, nativeSocket, &(context->_inStream), &(context->_outStream)); // Require both streams in order to create. if ((context->_inStream == NULL) || (context->_outStream == NULL)) break; // Give up ownership of the native socket. CFReadStreamSetProperty(context->_inStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); // Create the receive buffer of no fixed size. context->_rcvdBytes = CFDataCreateMutable(alloc, 0); // Fail if unable to create receive buffer. if (context->_rcvdBytes == NULL) break; // Create the outbound buffer of no fixed size. context->_sendBytes = CFDataCreateMutable(alloc, 0); // Fail if unable to create send buffer. if (context->_sendBytes == NULL) break; context->_request = CFAllocatorAllocate(alloc, sizeof(context->_request[0]), 0); // Fail if unable to create request. if (context->_request == NULL) break; memset(context->_request, 0, sizeof(context->_request[0])); return context; } while (0); // Something failed, so clean up. HttpContextRelease(context); return NULL; }
static void flatten(SCPreferencesRef prefs, CFStringRef key, CFDictionaryRef base) { CFDictionaryRef subset; CFStringRef link; CFMutableDictionaryRef myDict; CFStringRef myKey; CFIndex i; CFIndex nKeys; const void **keys; const void **vals; if (!CFDictionaryGetValueIfPresent(base, kSCResvLink, (const void **)&link)) { /* if this dictionary is not linked */ subset = base; } else { /* if __LINK__ key is present */ subset = SCPreferencesPathGetValue(prefs, link); if (!subset) { /* if error with link */ SCLog(TRUE, LOG_ERR, CFSTR("SCPreferencesPathGetValue(,%@,) failed: %s"), link, SCErrorString(SCError())); return; } } if (CFDictionaryContainsKey(subset, kSCResvInactive)) { /* if __INACTIVE__ key is present */ return; } myKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), kSCDynamicStoreDomainSetup, key); myDict = (CFMutableDictionaryRef)CFDictionaryGetValue(newPrefs, myKey); if (myDict) { myDict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)myDict); } else { myDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } nKeys = CFDictionaryGetCount(subset); if (nKeys > 0) { keys = CFAllocatorAllocate(NULL, nKeys * sizeof(CFStringRef) , 0); vals = CFAllocatorAllocate(NULL, nKeys * sizeof(CFPropertyListRef), 0); CFDictionaryGetKeysAndValues(subset, keys, vals); for (i = 0; i < nKeys; i++) { if (CFGetTypeID((CFTypeRef)vals[i]) != CFDictionaryGetTypeID()) { /* add this key/value to the current dictionary */ CFDictionarySetValue(myDict, keys[i], vals[i]); } else { CFStringRef subKey; /* flatten [sub]dictionaries */ subKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%s%@"), key, CFEqual(key, CFSTR("/")) ? "" : "/", keys[i]); flatten(prefs, subKey, vals[i]); CFRelease(subKey); } } CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, vals); } if (CFDictionaryGetCount(myDict) > 0) { /* add this dictionary to the new preferences */ CFDictionarySetValue(newPrefs, myKey, myDict); } CFRelease(myDict); CFRelease(myKey); return; }
static void updateSCDynamicStore(SCPreferencesRef prefs) { CFStringRef current = NULL; CFDateRef date = NULL; CFMutableDictionaryRef dict = NULL; CFDictionaryRef global = NULL; CFIndex i; CFArrayRef keys; CFIndex n; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef set = NULL; /* * initialize old preferences, new preferences, an array * of keys which have not changed, and an array of keys * to be removed (cleaned up). */ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); pattern = CFStringCreateWithFormat(NULL, NULL, CFSTR("^%@.*"), kSCDynamicStoreDomainSetup); CFArrayAppendValue(patterns, pattern); dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); CFRelease(pattern); if (dict) { currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict); CFRelease(dict); } else { currentPrefs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); i = CFDictionaryGetCount(currentPrefs); if (i > 0) { const void **currentKeys; CFArrayRef array; currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0); CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL); array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks); removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array); CFRelease(array); CFAllocatorDeallocate(NULL, currentKeys); } else { removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } /* * The "newPrefs" dictionary will contain the new / updated * configuration which will be written to the configuration cache. */ newPrefs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* * create status dictionary associated with current configuration * information including: * - current set "name" to cache * - time stamp indicating when the cache preferences were * last updated. */ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); /* * load preferences */ keys = SCPreferencesCopyKeyList(prefs); if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) { SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences.")); goto done; } /* * get "global" system preferences */ global = SCPreferencesGetValue(prefs, kSCPrefSystem); if (!global) { /* if no global preferences are defined */ goto getSet; } if (!isA_CFDictionary(global)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a dictionary."), kSCPrefSystem); goto done; } /* flatten property list */ flatten(prefs, CFSTR("/"), global); getSet : /* * get current set name */ current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet); if (!current) { /* if current set not defined */ goto done; } if (!isA_CFString(current)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a string."), kSCPrefCurrentSet); goto done; } /* * get current set */ set = SCPreferencesPathGetValue(prefs, current); if (!set) { /* if error with path */ SCLog(TRUE, LOG_ERR, CFSTR("%@ value (%@) not valid"), kSCPrefCurrentSet, current); goto done; } if (!isA_CFDictionary(set)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a dictionary."), current); goto done; } /* flatten property list */ flatten(prefs, CFSTR("/"), set); CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current); done : /* add last updated time stamp */ CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date); /* add Setup: key */ CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict); /* compare current and new preferences */ CFDictionaryApplyFunction(newPrefs, updateCache, NULL); /* remove those keys which have not changed from the update */ n = CFArrayGetCount(unchangedPrefsKeys); for (i = 0; i < n; i++) { CFStringRef key; key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i); CFDictionaryRemoveValue(newPrefs, key); } /* Update the dynamic store */ #ifndef MAIN if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetMultiple() failed: %s"), SCErrorString(SCError())); } #else // !MAIN SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStore\nset: %@\nremove: %@\n"), newPrefs, removedPrefsKeys); #endif // !MAIN CFRelease(currentPrefs); CFRelease(newPrefs); CFRelease(unchangedPrefsKeys); CFRelease(removedPrefsKeys); if (dict) CFRelease(dict); if (date) CFRelease(date); if (keys) CFRelease(keys); return; }
static void *__CFAllocatorCustomValloc(malloc_zone_t *zone, size_t size) { CFAllocatorRef allocator = (CFAllocatorRef)zone; void *newptr = CFAllocatorAllocate(allocator, size + vm_page_size, 0); newptr = (void *)round_page((uintptr_t)newptr); return newptr; }
static CFStringRef copyVPNInterfaceNAP (char *interface_buf) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; void ** keys = (__typeof__(keys))keys_q; const void * values_q[128]; void ** values = (__typeof__(values))values_q; CFIndex n; CFStringRef vpn_if = NULL; CFStringRef result = NULL; if (!interface_buf) { return NULL; } if (gDynamicStore) { vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, NULL); CFRelease(interf_keys); if (!dict) { // if we could not access the SCDynamicStore goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, (const void **)keys, (const void **)values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFDictionaryRef i_dict = NULL; CFStringRef nap; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } i_dict = CFDictionaryGetValue(s_dict, KEY_VPNNETWORKLOCATION_INTERFINFO); if (!isA_CFDictionary(i_dict)) { continue; } nap = CFDictionaryGetValue(i_dict, KEY_VPNNETWORKLOCATION_SSID); if (nap) { result = CFStringCreateCopy(NULL, nap); SCLog(TRUE, LOG_INFO, CFSTR("%s: found nap %@, interf %s"), __FUNCTION__, result, interface_buf); goto done; } } done : if (vpn_if) CFRelease(vpn_if); if (keys != (__typeof__(keys))keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } if (dict) CFRelease(dict); } return result; }
int checkVPNInterfaceOrServiceBlocked (const char *location, char *interface_buf) { // check to see if interface is captive: if so, bail if the interface is not ready. if (check_interface_captive_and_not_ready(gDynamicStore, interface_buf)) { // TODO: perhaps we should wait for a few seconds? return true; } // return 1, if this is a delete event, and; // TODO: add support for IPv6 <rdar://problem/5920237> // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 if (gDynamicStore) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; const void ** keys = keys_q; const void * values_q[128]; const void ** values = values_q; CFIndex n; CFStringRef vpn_if; int other_serv_found = 0, interf_down = 0; vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString syslog(LOG_NOTICE, "%s: failed to initialize interface CFString", location); goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get Setup:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainSetup, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get Setup:/Network/Service/*/Interface pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); // get Setup:/Network/Service/*/IPv4 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, patterns); CFRelease(interf_keys); CFRelease(patterns); if (!dict) { // if we could not access the SCDynamicStore syslog(LOG_NOTICE, "%s: failed to initialize SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { syslog(LOG_NOTICE, "%s: empty SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, keys, values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFStringRef s_if; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { // is a Service Interface entity s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { CFArrayRef components; CFStringRef serviceIDRef = NULL, serviceKey = NULL; other_serv_found = 1; // extract service ID components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); if (CFArrayGetCount(components) > 3) { serviceIDRef = CFArrayGetValueAtIndex(components, 3); //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); if (!serviceKey || !CFDictionaryGetValue(dict, serviceKey)) { syslog(LOG_NOTICE, "%s: detected disabled IPv4 Config", location); interf_down = 1; } if (serviceKey) CFRelease(serviceKey); } if (components) CFRelease(components); if (interf_down) break; } continue; } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { // Interface/<vpn_if>/Airport entity if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, kSCPropNetAirPortPowerEnabled); if (isA_CFBoolean(powerEnable) && CFEqual(powerEnable, kCFBooleanFalse)) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerEnable == FALSE", location); interf_down = 1; break; } } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { UInt16 temp; CFNumberRef airStatus = CFDictionaryGetValue(s_dict, CFSTR("Power Status")); if (isA_CFNumber(airStatus) && CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { if (temp ==0) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerStatus == 0", location); } } } continue; } } if (vpn_if) CFRelease(vpn_if); if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } done : if (dict) CFRelease(dict); return (other_serv_found == 0 || interf_down == 1); } return 0; }
WebSocketRef WebSocketCreateWithHostAndPort (CFAllocatorRef allocator, CFStringRef host, UInt16 port, void *userInfo) { WebSocketRef self = CFAllocatorAllocate(allocator, sizeof(WebSocket), 0); if (self) { self->allocator = allocator ? CFRetain(allocator) : NULL; self->retainCount = 1; self->userInfo = userInfo; self->clientsLength = 1024; self->clientsUsedLength = 0; if (NULL == (self->clients = CFAllocatorAllocate(allocator, self->clientsLength, 0))) { WebSocketRelease(self), self = NULL; goto fin; } // Callbacks self->callbacks.didAddClientCallback = NULL; self->callbacks.willRemoveClientCallback = NULL; self->callbacks.didClientReadCallback = NULL; // Setup the context; CFSocketContext context = { .copyDescription = NULL, .retain = NULL, .release = NULL, .version = 0, .info = self }; if (NULL == (self->socket = CFSocketCreate(self->allocator, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, __WebSocketAcceptCallBack, &context))) { WebSocketRelease(self), self = NULL; goto fin; } // Re-use local addresses, if they're still in TIME_WAIT int yes = 1; setsockopt(CFSocketGetNative(self->socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); // Set the port and address we want to listen on memset(&self->addr, 0, sizeof(self->addr)); self->addr.sin_len = sizeof(self->addr); self->addr.sin_family = AF_INET; if (CFEqual(kWebSocketHostAny, host)) { // Host is set to "0.0.0.0", set it to INADDR_ANY self->addr.sin_addr.s_addr = htonl(INADDR_ANY); } else { // Set the host based on provided string. TODO: hostname resolution? CFIndex hostCStringLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(host), kCFStringEncodingASCII) + 1; char *hostCString = CFAllocatorAllocate(self->allocator, hostCStringLength, 0); if (hostCString) { if (CFStringGetCString(host, hostCString, hostCStringLength, kCFStringEncodingASCII)) { inet_aton(hostCString, &self->addr.sin_addr); } else { // TODO: Couldn't get CString } CFAllocatorDeallocate(self->allocator, hostCString); } else { // TODO: Couldn't allocate buffer } } self->addr.sin_port = htons(port); CFDataRef address = CFDataCreate(self->allocator, (const void *) &self->addr, sizeof(self->addr)); if (address) { if (CFSocketSetAddress(self->socket, (CFDataRef) address) != kCFSocketSuccess) { WebSocketRelease(self), self = NULL; CFRelease(address); goto fin; } CFRelease(address); } // Create run loop source and add it to the current run loop CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(self->allocator, self->socket, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); CFRelease(source); } fin: return self; } WebSocketRef WebSocketCreate (CFAllocatorRef allocator, void *userInfo) { return WebSocketCreateWithHostAndPort(allocator, kWebSocketHostLoopBack, kWebSocketPortAny, userInfo); } void WebSocketRetain (WebSocketRef self) { if_self { ++self->retainCount; } }
__private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength) { // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length. struct stat statBuf; int fd = -1; char path[CFMaxPathSize]; if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize)) { return false; } *bytes = NULL; #if DEPLOYMENT_TARGET_WINDOWS || 0 fd = open(path, O_RDONLY|CF_OPENFLGS, 0666|_S_IREAD); #else int no_hang_fd = open("/dev/autofs_nowait", 0); fd = open(path, O_RDONLY|CF_OPENFLGS, 0666); #endif if (fd < 0) { #if !DEPLOYMENT_TARGET_WINDOWS close(no_hang_fd); #endif return false; } if (fstat(fd, &statBuf) < 0) { int saveerr = thread_errno(); close(fd); #if !DEPLOYMENT_TARGET_WINDOWS close(no_hang_fd); #endif thread_set_errno(saveerr); return false; } if ((statBuf.st_mode & S_IFMT) != S_IFREG) { close(fd); #if !DEPLOYMENT_TARGET_WINDOWS close(no_hang_fd); #endif thread_set_errno(EACCES); return false; } if (statBuf.st_size == 0) { *bytes = CFAllocatorAllocate(alloc, 4, 0); // don't return constant string -- it's freed! if (__CFOASafe) __CFSetLastAllocationEventName(*bytes, "CFUtilities (file-bytes)"); *length = 0; } else { CFIndex desiredLength; if ((maxLength >= statBuf.st_size) || (maxLength == 0)) { desiredLength = statBuf.st_size; } else { desiredLength = maxLength; } *bytes = CFAllocatorAllocate(alloc, desiredLength, 0); if (__CFOASafe) __CFSetLastAllocationEventName(*bytes, "CFUtilities (file-bytes)"); // fcntl(fd, F_NOCACHE, 1); if (read(fd, *bytes, desiredLength) < 0) { CFAllocatorDeallocate(alloc, *bytes); close(fd); #if !DEPLOYMENT_TARGET_WINDOWS close(no_hang_fd); #endif return false; } *length = desiredLength; } close(fd); #if !DEPLOYMENT_TARGET_WINDOWS close(no_hang_fd); #endif return true; }
static void _copyAddlDataForType(CFAllocatorRef alloc, CFXMLNodeTypeCode xmlType, const void *src, void *dest) { switch(xmlType) { case kCFXMLNodeTypeDocument: { CFXMLDocumentInfo *srcData = (CFXMLDocumentInfo *)src; CFXMLDocumentInfo *destData = (CFXMLDocumentInfo *)dest; destData->sourceURL = srcData->sourceURL ? (CFURLRef)CFRetain(srcData->sourceURL) : NULL; destData->encoding = srcData->encoding; break; } case kCFXMLNodeTypeElement: { CFXMLElementInfo *srcData = (CFXMLElementInfo *)src; CFXMLElementInfo *destData = (CFXMLElementInfo *)dest; if (srcData->attributes && CFDictionaryGetCount(srcData->attributes) != 0) { destData->attributes = (CFDictionaryRef)CFPropertyListCreateDeepCopy(alloc, srcData->attributes, kCFPropertyListImmutable); destData->attributeOrder = (CFArrayRef)CFPropertyListCreateDeepCopy(alloc, srcData->attributeOrder, kCFPropertyListImmutable); } else { destData->attributes = NULL; destData->attributeOrder = NULL; } destData->isEmpty = srcData->isEmpty; break; } case kCFXMLNodeTypeProcessingInstruction: { CFXMLProcessingInstructionInfo *srcData = (CFXMLProcessingInstructionInfo *)src; CFXMLProcessingInstructionInfo *destData = (CFXMLProcessingInstructionInfo *)dest; destData->dataString = srcData->dataString ? (CFStringRef)CFStringCreateCopy(alloc, srcData->dataString) : NULL; break; } case kCFXMLNodeTypeEntity: { CFXMLEntityInfo *sourceData = (CFXMLEntityInfo *)src; CFXMLEntityInfo *destData = (CFXMLEntityInfo *)dest; destData->entityType = sourceData->entityType; destData->replacementText = sourceData->replacementText ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->replacementText) : NULL; destData->entityID.systemID = sourceData->entityID.systemID ? (CFURLRef)CFRetain(sourceData->entityID.systemID) : NULL; destData->entityID.publicID = sourceData->entityID.publicID ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->entityID.publicID) : NULL; destData->notationName = sourceData->notationName ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->notationName) : NULL; break; } case kCFXMLNodeTypeEntityReference: { CFXMLEntityReferenceInfo *srcData = (CFXMLEntityReferenceInfo *)src; CFXMLEntityReferenceInfo *destData = (CFXMLEntityReferenceInfo *)dest; destData->entityType = srcData->entityType; break; } case kCFXMLNodeTypeDocumentType: case kCFXMLNodeTypeNotation: { // We can get away with this because the structures of CFXMLNotationInfo and CFXMLDocumentTypeInfo match. -- REW, 3/8/2000 CFXMLNotationInfo *srcData = (CFXMLNotationInfo *)src; CFXMLNotationInfo *destData = (CFXMLNotationInfo *)dest; destData->externalID.systemID = srcData->externalID.systemID ? (CFURLRef)CFRetain(srcData->externalID.systemID) : NULL; destData->externalID.publicID = srcData->externalID.publicID ? (CFStringRef)CFStringCreateCopy(alloc, srcData->externalID.publicID) : NULL; break; } case kCFXMLNodeTypeElementTypeDeclaration: { CFXMLElementTypeDeclarationInfo *srcData = (CFXMLElementTypeDeclarationInfo *)src; CFXMLElementTypeDeclarationInfo *destData = (CFXMLElementTypeDeclarationInfo *)dest; destData->contentDescription = srcData->contentDescription ? (CFStringRef)CFStringCreateCopy(alloc, srcData->contentDescription) : NULL; break; } case kCFXMLNodeTypeAttributeListDeclaration: { CFXMLAttributeListDeclarationInfo *sourceData = (CFXMLAttributeListDeclarationInfo *)src; CFXMLAttributeListDeclarationInfo *destData = (CFXMLAttributeListDeclarationInfo *)dest; CFIndex idx; destData->numberOfAttributes = sourceData->numberOfAttributes; destData->attributes = sourceData->numberOfAttributes ? (CFXMLAttributeDeclarationInfo *)CFAllocatorAllocate(alloc, sizeof(CFXMLAttributeDeclarationInfo)*sourceData->numberOfAttributes, 0) : NULL; for (idx = 0; idx < sourceData->numberOfAttributes; idx ++) { CFXMLAttributeDeclarationInfo sourceAttr = sourceData->attributes[idx]; CFXMLAttributeDeclarationInfo *destAttr = &(destData->attributes[idx]); destAttr->attributeName = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.attributeName); destAttr->typeString = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.typeString); destAttr->defaultString = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.defaultString); } break; } default: CFAssert2(false, __kCFLogAssertion, "%s(): Encountered unexpected typeID %d (additionalData should be empty)", __PRETTY_FUNCTION__, xmlType); } }
CF_PRIVATE CFTypeRef __CFCreateOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format) { // Convert the string to UTF16 for parsing old-style if (originalString) { // Ensure that originalString is not collected while we are using it CFRetain(originalString); } else { originalString = CFStringCreateWithBytes(kCFAllocatorSystemDefault, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData), guessedEncoding, NO); if (!originalString) { // Couldn't convert if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed.")); return NULL; } } UInt32 length; Boolean createdBuffer = false; length = CFStringGetLength(originalString); if (!length) { if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed. The string is empty.")); return NULL; } UniChar *buf = (UniChar *)CFStringGetCharactersPtr(originalString); if (!buf) { buf = (UniChar *)CFAllocatorAllocate(allocator, length * sizeof(UniChar), 0); if (!buf) { CRSetCrashLogMessage("CFPropertyList ran out of memory while attempting to allocate temporary storage."); return NULL; } CFStringGetCharacters(originalString, CFRangeMake(0, length), buf); createdBuffer = true; } _CFStringsFileParseInfo stringsPInfo; stringsPInfo.begin = buf; stringsPInfo.end = buf+length; stringsPInfo.curr = buf; stringsPInfo.allocator = allocator; stringsPInfo.mutabilityOption = option; stringsPInfo.stringSet = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks); stringsPInfo.error = NULL; const UniChar *begin = stringsPInfo.curr; CFTypeRef result = NULL; Boolean foundChar = advanceToNonSpace(&stringsPInfo); if (!foundChar) { // A file consisting only of whitespace (or empty) is now defined to be an empty dictionary result = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } else { result = parsePlistObject(&stringsPInfo, true); if (result) { foundChar = advanceToNonSpace(&stringsPInfo); if (foundChar) { if (CFGetTypeID(result) != CFStringGetTypeID()) { if (result) CFRelease(result); result = NULL; if (stringsPInfo.error) CFRelease(stringsPInfo.error); stringsPInfo.error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Junk after plist at line %d"), lineNumberStrings(&stringsPInfo)); } else { // Reset info and keep parsing if (result) CFRelease(result); if (stringsPInfo.error) CFRelease(stringsPInfo.error); stringsPInfo.error = NULL; // Check for a strings file (looks like a dictionary without the opening/closing curly braces) stringsPInfo.curr = begin; result = parsePlistDictContent(&stringsPInfo); } } } } if (!result) { // Must return some kind of error if requested if (outError) { if (stringsPInfo.error) { // Transfer ownership *outError = stringsPInfo.error; } else { *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unknown error parsing property list around line %d"), lineNumberStrings(&stringsPInfo)); } } else if (stringsPInfo.error) { // Caller doesn't want it, so we need to free it CFRelease(stringsPInfo.error); } } if (result && format) *format = kCFPropertyListOpenStepFormat; if (createdBuffer) CFAllocatorDeallocate(allocator, buf); CFRelease(stringsPInfo.stringSet); CFRelease(originalString); return result; }
Boolean CFStringFindWithOptionsAndLocale (CFStringRef str, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFLocaleRef locale, CFRange *result) { UniChar *pattern; UniChar *text; CFIndex patternLength; CFIndex textLength; CFIndex start; CFIndex end; CFAllocatorRef alloc; UCollator *ucol; UStringSearch *usrch; UErrorCode err = U_ZERO_ERROR; if (rangeToSearch.length == 0) return false; alloc = CFAllocatorGetDefault (); textLength = CFStringGetLength (stringToFind); if (textLength == 0) return false; patternLength = rangeToSearch.length; pattern = CFAllocatorAllocate (alloc, patternLength * sizeof(UniChar), 0); CFStringGetCharacters (str, rangeToSearch, pattern); text = CFAllocatorAllocate (alloc, textLength * sizeof(UniChar), 0); CFStringGetCharacters (stringToFind, CFRangeMake(0, textLength), text); ucol = CFStringICUCollatorOpen (searchOptions, locale); usrch = usearch_openFromCollator (text, textLength, pattern, patternLength, ucol, NULL, &err); if (U_FAILURE(err)) return false; /* FIXME: need to handle kCFCompareAnchored */ if (searchOptions & kCFCompareBackwards) { start = usearch_last (usrch, &err); } else { start = usearch_first (usrch, &err); } if (start == USEARCH_DONE) { CFAllocatorDeallocate (alloc, pattern); CFAllocatorDeallocate (alloc, text); return false; } end = usearch_getMatchedLength (usrch); usearch_close (usrch); CFStringICUCollatorClose (ucol); if (result) *result = CFRangeMake (start + rangeToSearch.location, end); CFAllocatorDeallocate (alloc, pattern); CFAllocatorDeallocate (alloc, text); return true; }
int main(int argc, char * const argv[]) { Boolean doDNS = FALSE; Boolean doNet = FALSE; Boolean doNWI = FALSE; Boolean doPrefs = FALSE; Boolean doProxy = FALSE; Boolean doReach = FALSE; Boolean doSnap = FALSE; char *get = NULL; char *log = NULL; extern int optind; int opt; int opti; const char *prog = argv[0]; char *renew = NULL; char *set = NULL; char *nc_cmd = NULL; InputRef src; int timeout = 15; /* default timeout (in seconds) */ char *wait = NULL; Boolean watch = FALSE; int xStore = 0; /* non dynamic store command line options */ /* process any arguments */ while ((opt = getopt_long(argc, argv, "dDvprt:w:W", longopts, &opti)) != -1) switch(opt) { case 'd': _sc_debug = TRUE; _sc_log = FALSE; /* enable framework logging */ break; case 'D': doDispatch = TRUE; break; case 'v': _sc_verbose = TRUE; _sc_log = FALSE; /* enable framework logging */ break; case 'p': enablePrivateAPI = TRUE; break; case 'r': doReach = TRUE; xStore++; break; case 't': timeout = atoi(optarg); break; case 'w': wait = optarg; xStore++; break; case 'W': watch = TRUE; break; case 0: if (strcmp(longopts[opti].name, "dns") == 0) { doDNS = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "get") == 0) { get = optarg; xStore++; } else if (strcmp(longopts[opti].name, "nc") == 0) { nc_cmd = optarg; xStore++; } else if (strcmp(longopts[opti].name, "net") == 0) { doNet = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "nwi") == 0) { doNWI = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "prefs") == 0) { doPrefs = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "proxy") == 0) { doProxy = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "renew") == 0) { renew = optarg; xStore++; } else if (strcmp(longopts[opti].name, "set") == 0) { set = optarg; xStore++; } else if (strcmp(longopts[opti].name, "snapshot") == 0) { doSnap = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "log") == 0) { log = optarg; xStore++; } else if (strcmp(longopts[opti].name, "user") == 0) { username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } else if (strcmp(longopts[opti].name, "password") == 0) { password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } else if (strcmp(longopts[opti].name, "secret") == 0) { sharedsecret = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } break; case '?': default : usage(prog); } argc -= optind; argv += optind; if (xStore > 1) { // if we are attempting to process more than one type of request usage(prog); } /* are we checking (or watching) the reachability of a host/address */ if (doReach) { if (argc < 1) { usage(prog); } if (watch) { do_watchReachability(argc, (char **)argv); } else { do_checkReachability(argc, (char **)argv); } /* NOT REACHED */ } /* are we waiting on the presense of a dynamic store key */ if (wait) { do_wait(wait, timeout); /* NOT REACHED */ } /* are we looking up the DNS configuration */ if (doDNS) { do_showDNSConfiguration(argc, (char **)argv); /* NOT REACHED */ } if (doNWI) { do_nwi(argc, (char**)argv); /* NOT REACHED */ } if (doSnap) { if (!enablePrivateAPI #if !TARGET_IPHONE_SIMULATOR || (geteuid() != 0) #endif // !TARGET_IPHONE_SIMULATOR ) { usage(prog); } do_open(0, NULL); /* open the dynamic store */ do_snapshot(argc, (char**)argv); exit(0); } /* are we looking up a preference value */ if (get) { if (argc != 2) { if (findPref(get) < 0) { usage(prog); } } else { /* need to go back one argument * for the filename */ argc++; argv--; } do_getPref(get, argc, (char **)argv); /* NOT REACHED */ } /* are we looking up the proxy configuration */ if (doProxy) { do_showProxyConfiguration(argc, (char **)argv); /* NOT REACHED */ } /* are we changing a preference value */ if (set) { if (findPref(set) < 0) { usage(prog); } do_setPref(set, argc, (char **)argv); /* NOT REACHED */ } /* verbose log */ if (log != NULL) { if (strcasecmp(log, "IPMonitor")) { usage(prog); } do_log(log, argc, (char * *)argv); /* NOT REACHED */ } /* network connection commands */ if (nc_cmd) { if (find_nc_cmd(nc_cmd) < 0) { usage(prog); } do_nc_cmd(nc_cmd, argc, (char **)argv, watch); /* NOT REACHED */ } if (doNet) { /* if we are going to be managing the network configuration */ commands = (cmdInfo *)commands_net; nCommands = nCommands_net; if (!getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) { usage(prog); } do_net_init(); /* initialization */ do_net_open(argc, (char **)argv); /* open prefs */ } else if (doPrefs) { /* if we are going to be managing the network configuration */ commands = (cmdInfo *)commands_prefs; nCommands = nCommands_prefs; do_dictInit(0, NULL); /* start with an empty dictionary */ do_prefs_init(); /* initialization */ do_prefs_open(argc, (char **)argv); /* open prefs */ } else { /* if we are going to be managing the dynamic store */ commands = (cmdInfo *)commands_store; nCommands = nCommands_store; do_dictInit(0, NULL); /* start with an empty dictionary */ do_open(0, NULL); /* open the dynamic store */ } /* are we trying to renew a DHCP lease */ if (renew != NULL) { do_renew(renew); /* NOT REACHED */ } /* allocate command input stream */ src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); src->fp = stdin; src->el = NULL; src->h = NULL; if (isatty(fileno(src->fp))) { int editmode = 1; HistEvent ev; struct termios t; if (tcgetattr(fileno(src->fp), &t) != -1) { if ((t.c_lflag & ECHO) == 0) { editmode = 0; } } src->el = el_init(prog, src->fp, stdout, stderr); src->h = history_init(); (void)history(src->h, &ev, H_SETSIZE, INT_MAX); el_set(src->el, EL_HIST, history, src->h); if (!editmode) { el_set(src->el, EL_EDITMODE, 0); } el_set(src->el, EL_EDITOR, "emacs"); el_set(src->el, EL_PROMPT, prompt); el_source(src->el, NULL); if ((el_get(src->el, EL_EDITMODE, &editmode) != -1) && editmode != 0) { el_set(src->el, EL_SIGNAL, 1); } else { history_end(src->h); src->h = NULL; el_end(src->el); src->el = NULL; } } while (TRUE) { Boolean ok; ok = process_line(src); if (!ok) { break; } } /* close the socket, free resources */ if (src->h) history_end(src->h); if (src->el) el_end(src->el); (void)fclose(src->fp); CFAllocatorDeallocate(NULL, src); exit (EX_OK); // insure the process exit status is 0 return 0; // ...and make main fit the ANSI spec. }
// This function does no ObjC dispatch or argument checking; // It should only be called from places where that dispatch and check has already been done, or NSCFArray void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **newValues, CFIndex newCount) { CHECK_FOR_MUTATION(array); BEGIN_MUTATION(array); const CFArrayCallBacks *cb; CFIndex idx, cnt, futureCnt; const void **newv, *buffer[256]; cnt = __CFArrayGetCount(array); futureCnt = cnt - range.length + newCount; CFAssert1(newCount <= futureCnt, __kCFLogAssertion, "%s(): internal error 1", __PRETTY_FUNCTION__); cb = __CFArrayGetCallBacks(array); CFAllocatorRef allocator = __CFGetAllocator(array); /* Retain new values if needed, possibly allocating a temporary buffer for them */ if (NULL != cb->retain && !hasBeenFinalized(array)) { newv = (newCount <= 256) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, newCount * sizeof(void *), 0); // GC OK if (newv != buffer && __CFOASafe) __CFSetLastAllocationEventName(newv, "CFArray (temp)"); for (idx = 0; idx < newCount; idx++) { newv[idx] = (void *)INVOKE_CALLBACK2(cb->retain, allocator, (void *)newValues[idx]); } } else { newv = newValues; } array->_mutations++; /* Now, there are three regions of interest, each of which may be empty: * A: the region from index 0 to one less than the range.location * B: the region of the range * C: the region from range.location + range.length to the end * Note that index 0 is not necessarily at the lowest-address edge * of the available storage. The values in region B need to get * released, and the values in regions A and C (depending) need * to get shifted if the number of new values is different from * the length of the range being replaced. */ if (0 < range.length) { __CFArrayReleaseValues(array, range, false); } // region B elements are now "dead" if (0) { } else if (NULL == array->_store) { if (0) { } else if (0 <= futureCnt) { struct __CFArrayDeque *deque; CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); deque = (struct __CFArrayDeque *)CFAllocatorAllocate(_CFConvertAllocatorToGCRefZeroEquivalent(allocator), size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)"); deque->_leftIdx = (capacity - newCount) / 2; deque->_capacity = capacity; __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque); } } else { // Deque // reposition regions A and C for new region B elements in gap if (0) { } else if (range.length != newCount) { __CFArrayRepositionDequeRegions(array, range, newCount); } } // copy in new region B elements if (0 < newCount) { if (0) { } else { // Deque struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store; struct __CFArrayBucket *raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque)); objc_memmove_collectable(raw_buckets + deque->_leftIdx + range.location, newv, newCount * sizeof(struct __CFArrayBucket)); } } __CFArraySetCount(array, futureCnt); if (newv != buffer && newv != newValues) CFAllocatorDeallocate(kCFAllocatorSystemDefault, newv); END_MUTATION(array); }
static void *__CFAllocatorCustomMalloc(malloc_zone_t *zone, size_t size) { CFAllocatorRef allocator = (CFAllocatorRef)zone; return CFAllocatorAllocate(allocator, size, 0); }
__private_extern__ void configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { mig_reply_error_t * bufRequest = msg; uint32_t bufReply_q[MACH_MSG_BUFFER_SIZE/sizeof(uint32_t)]; mig_reply_error_t * bufReply = (mig_reply_error_t *)bufReply_q; static CFIndex bufSize = 0; mach_msg_return_t mr; int options; if (bufSize == 0) { // get max size for MiG reply buffers bufSize = _config_subsystem.maxsize; // check if our on-the-stack reply buffer will be big enough if (bufSize > sizeof(bufReply_q)) { SCLog(TRUE, LOG_NOTICE, CFSTR("configdCallback(): buffer size should be increased > %d"), _config_subsystem.maxsize); } } if (bufSize > sizeof(bufReply_q)) { bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0); } bufReply->RetCode = 0; /* we have a request message */ (void) config_demux(&bufRequest->Head, &bufReply->Head); if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { if (bufReply->RetCode == MIG_NO_REPLY) { bufReply->Head.msgh_remote_port = MACH_PORT_NULL; } else if ((bufReply->RetCode != KERN_SUCCESS) && (bufRequest->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { /* * destroy the request - but not the reply port */ bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; mach_msg_destroy(&bufRequest->Head); } } if (bufReply->Head.msgh_remote_port != MACH_PORT_NULL) { /* * send reply. * * We don't want to block indefinitely because the client * isn't receiving messages from the reply port. * If we have a send-once right for the reply port, then * this isn't a concern because the send won't block. * If we have a send right, we need to use MACH_SEND_TIMEOUT. * To avoid falling off the kernel's fast RPC path unnecessarily, * we only supply MACH_SEND_TIMEOUT when absolutely necessary. */ options = MACH_SEND_MSG; if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) { options |= MACH_SEND_TIMEOUT; } mr = mach_msg(&bufReply->Head, /* msg */ options, /* option */ bufReply->Head.msgh_size, /* send_size */ 0, /* rcv_size */ MACH_PORT_NULL, /* rcv_name */ MACH_MSG_TIMEOUT_NONE, /* timeout */ MACH_PORT_NULL); /* notify */ /* Has a message error occurred? */ switch (mr) { case MACH_SEND_INVALID_DEST: case MACH_SEND_TIMED_OUT: break; default : /* Includes success case. */ goto done; } } if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { mach_msg_destroy(&bufReply->Head); } done : if (bufReply != (mig_reply_error_t *)bufReply_q) CFAllocatorDeallocate(NULL, bufReply); return; }
static void *__CFAllocatorCustomCalloc(malloc_zone_t *zone, size_t num_items, size_t size) { CFAllocatorRef allocator = (CFAllocatorRef)zone; void *newptr = CFAllocatorAllocate(allocator, size, 0); if (newptr) memset(newptr, 0, size); return newptr; }
Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringEncoding encoding, Boolean alwaysUnicode, CFVarWidthCharBuffer *buffer, Boolean *useClientsMemoryPtr, UInt32 converterFlags) { CFIndex idx; const uint8_t *chars = (const uint8_t *)bytes; const uint8_t *end = chars + len; Boolean result = TRUE; if (useClientsMemoryPtr) *useClientsMemoryPtr = false; buffer->isASCII = !alwaysUnicode; buffer->shouldFreeChars = false; buffer->numChars = 0; if (0 == len) return true; buffer->allocator = (buffer->allocator ? buffer->allocator : __CFGetDefaultAllocator()); if ((encoding == kCFStringEncodingUTF16) || (encoding == kCFStringEncodingUTF16BE) || (encoding == kCFStringEncodingUTF16LE)) { // UTF-16 const UTF16Char *src = (const UTF16Char *)bytes; const UTF16Char *limit = src + (len / sizeof(UTF16Char)); // <rdar://problem/7854378> avoiding odd len issue bool swap = false; if (kCFStringEncodingUTF16 == encoding) { UTF16Char bom = ((*src == 0xFFFE) || (*src == 0xFEFF) ? *(src++) : 0); #if __CF_BIG_ENDIAN__ if (bom == 0xFFFE) swap = true; #else if (bom != 0xFEFF) swap = true; #endif if (bom) useClientsMemoryPtr = NULL; } else { #if __CF_BIG_ENDIAN__ if (kCFStringEncodingUTF16LE == encoding) swap = true; #else if (kCFStringEncodingUTF16BE == encoding) swap = true; #endif } buffer->numChars = limit - src; if (useClientsMemoryPtr && !swap) { // If the caller is ready to deal with no-copy situation, and the situation is possible, indicate it... *useClientsMemoryPtr = true; buffer->chars.unicode = (UniChar *)src; buffer->isASCII = false; } else { if (buffer->isASCII) { // Let's see if we can reduce the Unicode down to ASCII... const UTF16Char *characters = src; UTF16Char mask = (swap ? 0x80FF : 0xFF80); while (characters < limit) { if (*(characters++) & mask) { buffer->isASCII = false; break; } } } if (buffer->isASCII) { uint8_t *dst; if (NULL == buffer->chars.ascii) { // we never reallocate when buffer is supplied if (buffer->numChars > MAX_LOCAL_CHARS) { buffer->chars.ascii = (UInt8 *)CFAllocatorAllocate(buffer->allocator, (buffer->numChars * sizeof(uint8_t)), 0); if (!buffer->chars.ascii) goto memoryErrorExit; buffer->shouldFreeChars = true; } else { buffer->chars.ascii = (uint8_t *)buffer->localBuffer; } } dst = buffer->chars.ascii; if (swap) { while (src < limit) *(dst++) = (*(src++) >> 8); } else { while (src < limit) *(dst++) = (uint8_t)*(src++); } } else {
static void* handleIPCMessage (void* aMsgParam, CFIndex aMessageSize, CFAllocatorRef anAllocator, void* aMachPort) { SystemStarterIPCMessage* aMessage = (SystemStarterIPCMessage*) aMsgParam; SystemStarterIPCMessage* aReplyMessage = NULL; CFDataRef aResult = NULL; CFDataRef aData = NULL; if (aMessage->aHeader.msgh_bits & MACH_MSGH_BITS_COMPLEX) { warning(CFSTR("Ignoring out-of-line IPC message.\n")); return NULL; } else { mach_msg_security_trailer_t* aSecurityTrailer = (mach_msg_security_trailer_t*) ((uint8_t*)aMessage + round_msg(sizeof(SystemStarterIPCMessage) + aMessage->aByteLength)); /* CFRunLoop includes the format 0 message trailer with the passed message. */ if (aSecurityTrailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0 && aSecurityTrailer->msgh_sender.val[0] != 0) { warning(CFSTR("Ignoring IPC message sent from uid %d\n."), aSecurityTrailer->msgh_sender.val[0]); return NULL; } } if (aMessage->aProtocol != kIPCProtocolVersion) { warning(CFSTR("Unsupported IPC protocol version number: %d. Message ignored.\n"), aMessage->aProtocol); return NULL; } aData = CFDataCreateWithBytesNoCopy(NULL, (uint8_t*)aMessage + sizeof(SystemStarterIPCMessage), aMessage->aByteLength, kCFAllocatorNull); /* * Dispatch the IPC message. */ if (aData) { StartupContext aStartupContext = NULL; CFStringRef anErrorString = NULL; CFDictionaryRef anIPCMessage = (CFDictionaryRef) CFPropertyListCreateFromXMLData(NULL, aData, kCFPropertyListImmutable, &anErrorString); if (gDebugFlag == 2) debug(CFSTR("\nIPC message = %@\n"), anIPCMessage); if (aMachPort) { CFMachPortContext aMachPortContext; CFMachPortGetContext((CFMachPortRef)aMachPort, &aMachPortContext); aStartupContext = (StartupContext)aMachPortContext.info; } if (anIPCMessage && CFGetTypeID(anIPCMessage) == CFDictionaryGetTypeID()) { /* switch on the type of the IPC message */ CFStringRef anIPCMessageType = CFDictionaryGetValue(anIPCMessage, kIPCMessageKey); if (anIPCMessageType && CFGetTypeID(anIPCMessageType) == CFStringGetTypeID()) { if (CFEqual(anIPCMessageType, kIPCConsoleMessage)) { consoleMessage(aStartupContext, anIPCMessage); } else if (CFEqual(anIPCMessageType, kIPCStatusMessage)) { statusMessage(aStartupContext, anIPCMessage); } else if (CFEqual(anIPCMessageType, kIPCQueryMessage)) { aResult = queryConfigSetting(aStartupContext, anIPCMessage); } else if (CFEqual(anIPCMessageType, kIPCLoadDisplayBundleMessage)) { loadDisplayBundle(aStartupContext, anIPCMessage); } else if (CFEqual(anIPCMessageType, kIPCUnloadDisplayBundleMessage)) { unloadDisplayBundle(aStartupContext, anIPCMessage); } } } else { error(CFSTR("Unable to parse IPC message: %@\n"), anErrorString); } CFRelease(aData); } else { error(CFSTR("Out of memory. Could not allocate space for IPC message.\n")); } /* * Generate a Mach message for the result data. */ if (!aResult) aResult = CFDataCreateWithBytesNoCopy(NULL, "", 1, kCFAllocatorNull); if (aResult) { CFIndex aDataSize = CFDataGetLength(aResult); CFIndex aReplyMessageSize = round_msg(sizeof(SystemStarterIPCMessage) + aDataSize + 3); aReplyMessage = CFAllocatorAllocate(kCFAllocatorSystemDefault, aReplyMessageSize, 0); if (aReplyMessage) { aReplyMessage->aHeader.msgh_id = -1 * (SInt32)aMessage->aHeader.msgh_id; aReplyMessage->aHeader.msgh_size = aReplyMessageSize; aReplyMessage->aHeader.msgh_remote_port = aMessage->aHeader.msgh_remote_port; aReplyMessage->aHeader.msgh_local_port = MACH_PORT_NULL; aReplyMessage->aHeader.msgh_reserved = 0; aReplyMessage->aHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); aReplyMessage->aBody.msgh_descriptor_count = 0; aReplyMessage->aProtocol = kIPCProtocolVersion; aReplyMessage->aByteLength = CFDataGetLength(aResult); memmove((uint8_t*)aReplyMessage + sizeof(SystemStarterIPCMessage), CFDataGetBytePtr(aResult), CFDataGetLength(aResult)); } CFRelease(aResult); } if (!aReplyMessage) { error(CFSTR("Out of memory. Could not allocate IPC result.\n")); } return aReplyMessage; }