this repo has no description
at fixPythonPipStalling 1618 lines 39 kB view raw
1/* 2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * June 1, 2001 Allan Nathanson <ajn@apple.com> 28 * - public API conversion 29 * 30 * November 9, 2000 Allan Nathanson <ajn@apple.com> 31 * - initial revision 32 */ 33 34#define SC_LOG_HANDLE _SC_LOG_DEFAULT 35#include <SystemConfiguration/SystemConfiguration.h> 36#include <SystemConfiguration/SCValidation.h> 37#include <SystemConfiguration/SCPrivate.h> 38 39#include <sys/param.h> 40#include <sys/types.h> 41#include <sys/socket.h> 42#include <sys/ioctl.h> 43#include <net/if.h> 44#include <net/if_dl.h> 45#include <netinet/in.h> 46#include <arpa/inet.h> 47 48#include <dispatch/dispatch.h> 49 50#include <mach/mach.h> 51#include <mach/notify.h> 52#include <mach/mach_error.h> 53#include <pthread.h> 54 55#include <execinfo.h> 56#include <unistd.h> 57 58#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 59#include <CoreFoundation/CFUserNotification.h> 60#endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 61 62/* CrashReporter "Application Specific Information" */ 63#include <CrashReporterClient.h> 64 65#define N_QUICK 32 66 67 68#pragma mark - 69#pragma mark Miscellaneous 70 71 72__private_extern__ char * 73_SC_cfstring_to_cstring_ext(CFStringRef cfstr, char *buf, CFIndex bufLen, CFStringEncoding encoding, UInt8 lossByte, CFIndex *usedBufLen) 74{ 75 CFIndex converted; 76 CFIndex last = 0; 77 CFIndex len; 78 79 if (cfstr == NULL) { 80 cfstr = CFSTR(""); 81 } 82 len = CFStringGetLength(cfstr); 83 84 /* how much buffer space will we really need? */ 85 converted = CFStringGetBytes(cfstr, 86 CFRangeMake(0, len), 87 encoding, 88 lossByte, 89 FALSE, 90 NULL, 91 0, 92 &last); 93 if (converted < len) { 94 /* if full string could not be converted */ 95 if (buf != NULL) { 96 buf[0] = '\0'; 97 } 98 return NULL; 99 } 100 101 if (buf != NULL) { 102 if (bufLen < (last + 1)) { 103 /* if the size of the provided buffer is too small */ 104 buf[0] = '\0'; 105 return NULL; 106 } 107 } else { 108 /* allocate a buffer */ 109 bufLen = last + 1; 110 buf = CFAllocatorAllocate(NULL, bufLen, 0); 111 if (buf == NULL) { 112 return NULL; 113 } 114 } 115 116 (void)CFStringGetBytes(cfstr, 117 CFRangeMake(0, len), 118 encoding, 119 lossByte, 120 FALSE, 121 (UInt8 *)buf, 122 bufLen, 123 &last); 124 buf[last] = '\0'; 125 126 if (usedBufLen != NULL) { 127 *usedBufLen = last; 128 } 129 130 return buf; 131} 132 133 134char * 135_SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, CFIndex bufLen, CFStringEncoding encoding) 136{ 137 return _SC_cfstring_to_cstring_ext(cfstr, buf, bufLen, encoding, 0, NULL); 138 139} 140 141 142void 143_SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen) 144{ 145 union { 146 const struct sockaddr *sa; 147 const struct sockaddr_in *sin; 148 const struct sockaddr_in6 *sin6; 149 const struct sockaddr_dl *sdl; 150 } addr; 151 152 addr.sa = address; 153 154 memset(buf, 0, bufLen); 155 switch (address->sa_family) { 156 case AF_INET : 157 (void)inet_ntop(addr.sin->sin_family, 158 &addr.sin->sin_addr, 159 buf, 160 (socklen_t)bufLen); 161 break; 162 case AF_INET6 : { 163 (void)inet_ntop(addr.sin6->sin6_family, 164 &addr.sin6->sin6_addr, 165 buf, 166 (socklen_t)bufLen); 167 if (addr.sin6->sin6_scope_id != 0) { 168 size_t n; 169 170 n = strlen(buf); 171 if ((n+IF_NAMESIZE+1) <= bufLen) { 172 buf[n++] = '%'; 173 if_indextoname(addr.sin6->sin6_scope_id, &buf[n]); 174 } 175 } 176 break; 177 } 178 default : 179 snprintf(buf, bufLen, "unexpected address family %d", address->sa_family); 180 break; 181 } 182 183 return; 184} 185 186 187struct sockaddr * 188_SC_string_to_sockaddr(const char *str, sa_family_t af, void *buf, size_t bufLen) 189{ 190 union { 191 void *buf; 192 struct sockaddr *sa; 193 struct sockaddr_in *sin; 194 struct sockaddr_in6 *sin6; 195 } addr; 196 197 if (buf == NULL) { 198 bufLen = sizeof(struct sockaddr_storage); 199 addr.buf = CFAllocatorAllocate(NULL, bufLen, 0); 200 } else { 201 addr.buf = buf; 202 } 203 204 memset(addr.buf, 0, bufLen); 205 if (((af == AF_UNSPEC) || (af == AF_INET)) && 206 (bufLen >= sizeof(struct sockaddr_in)) && 207 inet_aton(str, &addr.sin->sin_addr) == 1) { 208 // if IPv4 address 209 addr.sin->sin_len = sizeof(struct sockaddr_in); 210 addr.sin->sin_family = AF_INET; 211 } else if (((af == AF_UNSPEC) || (af == AF_INET6)) && 212 (bufLen >= sizeof(struct sockaddr_in6)) && 213 inet_pton(AF_INET6, str, &addr.sin6->sin6_addr) == 1) { 214 // if IPv6 address 215 char *p; 216 217 addr.sin6->sin6_len = sizeof(struct sockaddr_in6); 218 addr.sin6->sin6_family = AF_INET6; 219 220 p = strchr(str, '%'); 221 if (p != NULL) { 222 addr.sin6->sin6_scope_id = if_nametoindex(p + 1); 223 } 224 225 if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6->sin6_addr) || 226 IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6->sin6_addr)) { 227 uint16_t if_index; 228 229 if_index = ntohs(addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1]); 230 addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; 231 if (addr.sin6->sin6_scope_id == 0) { 232 // use the scope id that was embedded in the [link local] IPv6 address 233 addr.sin6->sin6_scope_id = if_index; 234 } 235 } 236 } else { 237 if (addr.buf != buf) { 238 CFAllocatorDeallocate(NULL, addr.buf); 239 } 240 addr.buf = NULL; 241 } 242 243 return addr.sa; 244} 245 246 247void 248_SC_sendMachMessage(mach_port_t port, mach_msg_id_t msg_id) 249{ 250 mach_msg_empty_send_t msg; 251 mach_msg_option_t options; 252 kern_return_t status; 253 254 memset(&msg, 0, sizeof(msg)); 255 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); 256 msg.header.msgh_size = sizeof(msg); 257 msg.header.msgh_remote_port = port; 258 msg.header.msgh_local_port = MACH_PORT_NULL; 259 msg.header.msgh_id = msg_id; 260 options = MACH_SEND_TIMEOUT; 261 status = mach_msg(&msg.header, /* msg */ 262 MACH_SEND_MSG|options, /* options */ 263 msg.header.msgh_size, /* send_size */ 264 0, /* rcv_size */ 265 MACH_PORT_NULL, /* rcv_name */ 266 0, /* timeout */ 267 MACH_PORT_NULL); /* notify */ 268 if ((status == MACH_SEND_INVALID_DEST) || (status == MACH_SEND_TIMED_OUT)) { 269 mach_msg_destroy(&msg.header); 270 } 271 272 return; 273} 274 275 276CFStringRef 277_SC_trimDomain(CFStringRef domain) 278{ 279 CFIndex length; 280 281 if (!isA_CFString(domain)) { 282 return NULL; 283 } 284 285 // remove any leading/trailing dots 286 length = CFStringGetLength(domain); 287 if ((length > 0) && 288 (CFStringFindWithOptions(domain, 289 CFSTR("."), 290 CFRangeMake(0, 1), 291 kCFCompareAnchored, 292 NULL) || 293 CFStringFindWithOptions(domain, 294 CFSTR("."), 295 CFRangeMake(0, length), 296 kCFCompareAnchored|kCFCompareBackwards, 297 NULL)) 298 ) { 299 CFMutableStringRef trimmed; 300 301 trimmed = CFStringCreateMutableCopy(NULL, 0, domain); 302 CFStringTrim(trimmed, CFSTR(".")); 303 domain = (CFStringRef)trimmed; 304 length = CFStringGetLength(domain); 305 } else { 306 CFRetain(domain); 307 } 308 309 if (length == 0) { 310 CFRelease(domain); 311 domain = NULL; 312 } 313 314 return domain; 315} 316 317 318CFStringRef 319_SC_hw_model(Boolean trim) 320{ 321 static CFStringRef model = NULL; 322 static CFStringRef model_trimmed = NULL; 323 static dispatch_once_t once; 324 325 dispatch_once(&once, ^{ 326 char *cp; 327 char hwModel[64]; 328 int mib[] = { CTL_HW, HW_MODEL }; 329 size_t n = sizeof(hwModel); 330 int ret; 331 332 // get HW model name 333 memset(&hwModel, 0, sizeof(hwModel)); 334 ret = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &hwModel, &n, NULL, 0); 335 if (ret != 0) { 336 SC_log(LOG_NOTICE, "sysctl() CTL_HW/HW_MODEL failed: %s", strerror(errno)); 337 return; 338 } 339 hwModel[sizeof(hwModel) - 1] = '\0'; 340 model = CFStringCreateWithCString(NULL, hwModel, kCFStringEncodingASCII); 341 342 // and the "trimmed" name 343 // ... remove everything after (and including) a comma 344 // ... and then any trailing digits 345 cp = index(hwModel, ','); 346 if (cp != NULL) { 347 *cp = '\0'; 348 } 349 n = strlen(hwModel) - 1; 350 while (n > 0) { 351 if (!isdigit(hwModel[n])) { 352 break; 353 } 354 hwModel[n--] = '\0'; 355 } 356 model_trimmed = CFStringCreateWithCString(NULL, hwModel, kCFStringEncodingASCII); 357 }); 358 359 return trim ? model_trimmed : model; 360} 361 362 363#pragma mark - 364#pragma mark Serialization 365 366 367static kern_return_t 368__CFDataCopyVMData(CFDataRef data, void **dataRef, CFIndex *dataLen) 369{ 370 kern_return_t kr; 371 372 vm_address_t vm_address; 373 vm_size_t vm_size; 374 375 vm_address = (vm_address_t)CFDataGetBytePtr(data); 376 vm_size = (vm_size_t)CFDataGetLength(data); 377 kr = vm_allocate(mach_task_self(), &vm_address, vm_size, VM_FLAGS_ANYWHERE); 378 if (kr != KERN_SUCCESS) { 379 *dataRef = NULL; 380 *dataLen = 0; 381 return kr; 382 } 383 384 memcpy((void *)vm_address, (char *)CFDataGetBytePtr(data), vm_size); 385 *dataRef = (void *)vm_address; 386 *dataLen = vm_size; 387 388 return kr; 389} 390 391 392Boolean 393_SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dataLen) 394{ 395 CFDataRef myXml; 396 397 if ((xml == NULL) && ((dataRef == NULL) || (dataLen == NULL))) { 398 /* if not keeping track of allocated space */ 399 return FALSE; 400 } 401 402 myXml = CFPropertyListCreateData(NULL, 403 obj, 404 kCFPropertyListBinaryFormat_v1_0, 405 0, 406 NULL); 407 if (myXml == NULL) { 408 SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed"); 409 if (xml != NULL) { 410 *xml = NULL; 411 } 412 if ((dataRef != NULL) && (dataLen != NULL)) { 413 *dataLen = 0; 414 *dataRef = NULL; 415 } 416 return FALSE; 417 } 418 419 if (xml != NULL) { 420 *xml = myXml; 421 if ((dataRef != NULL) && (dataLen != NULL)) { 422 *dataRef = (void *)CFDataGetBytePtr(myXml); 423 *dataLen = CFDataGetLength(myXml); 424 } 425 } else { 426 kern_return_t kr; 427 428 kr = __CFDataCopyVMData(myXml, dataRef, dataLen); 429 CFRelease(myXml); 430 if (kr != KERN_SUCCESS) { 431 SC_log(LOG_NOTICE, "__CFDataCreateVMData() failed: %s", mach_error_string(kr)); 432 return FALSE; 433 } 434 } 435 436 return TRUE; 437} 438 439 440Boolean 441_SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dataLen) 442{ 443 CFErrorRef error = NULL; 444 445 if (xml == NULL) { 446 kern_return_t status; 447 448 xml = CFDataCreateWithBytesNoCopy(NULL, (void *)dataRef, dataLen, kCFAllocatorNull); 449 *obj = CFPropertyListCreateWithData(NULL, xml, kCFPropertyListImmutable, NULL, &error); 450 CFRelease(xml); 451 452 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); 453 if (status != KERN_SUCCESS) { 454 SC_log(LOG_NOTICE, "vm_deallocate() failed: %s", mach_error_string(status)); 455 /* non-fatal???, proceed */ 456 } 457 } else { 458 *obj = CFPropertyListCreateWithData(NULL, xml, kCFPropertyListImmutable, NULL, &error); 459 } 460 461 if (*obj == NULL) { 462 if (error != NULL) { 463 SC_log(LOG_NOTICE, "CFPropertyListCreateWithData() failed: %@", error); 464 CFRelease(error); 465 } 466 _SCErrorSet(kSCStatusFailed); 467 return FALSE; 468 } 469 470 return TRUE; 471} 472 473 474Boolean 475_SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *dataLen) 476{ 477 CFDataRef myData; 478 479 if (!isA_CFString(str)) { 480 /* if not a CFString */ 481 return FALSE; 482 } 483 484 if ((data == NULL) && ((dataRef == NULL) || (dataLen == NULL))) { 485 /* if not keeping track of allocated space */ 486 return FALSE; 487 } 488 489 myData = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0); 490 if (myData == NULL) { 491 SC_log(LOG_NOTICE, "CFStringCreateExternalRepresentation() failed"); 492 if (data != NULL) { 493 *data = NULL; 494 } 495 if ((dataRef != NULL) && (dataLen != NULL)) { 496 *dataRef = NULL; 497 *dataLen = 0; 498 } 499 return FALSE; 500 } 501 502 if (data != NULL) { 503 *data = myData; 504 if ((dataRef != NULL) && (dataLen != NULL)) { 505 *dataRef = (void *)CFDataGetBytePtr(myData); 506 *dataLen = CFDataGetLength(myData); 507 } 508 } else { 509 kern_return_t kr; 510 511 kr = __CFDataCopyVMData(myData, dataRef, dataLen); 512 CFRelease(myData); 513 if (kr != KERN_SUCCESS) { 514 SC_log(LOG_NOTICE, "__CFDataCreateVMData() failed: %s", mach_error_string(kr)); 515 return FALSE; 516 } 517 } 518 519 return TRUE; 520} 521 522 523Boolean 524_SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex dataLen) 525{ 526 if (utf8 == NULL) { 527 kern_return_t status; 528 529 utf8 = CFDataCreateWithBytesNoCopy(NULL, dataRef, dataLen, kCFAllocatorNull); 530 *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8); 531 CFRelease(utf8); 532 533 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); 534 if (status != KERN_SUCCESS) { 535 SC_log(LOG_NOTICE, "vm_deallocate() failed: %s", mach_error_string(status)); 536 /* non-fatal???, proceed */ 537 } 538 } else { 539 *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8); 540 } 541 542 if (*str == NULL) { 543 SC_log(LOG_NOTICE, "CFStringCreateFromExternalRepresentation() failed"); 544 return FALSE; 545 } 546 547 return TRUE; 548} 549 550 551Boolean 552_SCSerializeData(CFDataRef data, void **dataRef, CFIndex *dataLen) 553{ 554 kern_return_t kr; 555 556 if (!isA_CFData(data)) { 557 /* if not a CFData */ 558 return FALSE; 559 } 560 561 kr = __CFDataCopyVMData(data, dataRef, dataLen); 562 if (kr != KERN_SUCCESS) { 563 SC_log(LOG_NOTICE, "__CFDataCreateVMData() failed: %s", mach_error_string(kr)); 564 return FALSE; 565 } 566 567 return TRUE; 568} 569 570 571Boolean 572_SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen) 573{ 574 kern_return_t status; 575 576 *data = CFDataCreate(NULL, dataRef, dataLen); 577 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); 578 if (status != KERN_SUCCESS) { 579 SC_log(LOG_NOTICE, "vm_deallocate() failed: %s", mach_error_string(status)); 580 _SCErrorSet(kSCStatusFailed); 581 return FALSE; 582 } 583 584 return TRUE; 585} 586 587 588CF_RETURNS_RETAINED CFDictionaryRef 589_SCSerializeMultiple(CFDictionaryRef dict) 590{ 591 CFIndex i; 592 const void * keys_q[N_QUICK]; 593 const void ** keys = keys_q; 594 CFIndex nElements; 595 CFDictionaryRef newDict = NULL; 596 const void * pLists_q[N_QUICK]; 597 const void ** pLists = pLists_q; 598 const void * values_q[N_QUICK]; 599 const void ** values = values_q; 600 601 nElements = CFDictionaryGetCount(dict); 602 if (nElements > 0) { 603 if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 604 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 605 values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 606 pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFDataRef), 0); 607 } 608 memset(pLists, 0, nElements * sizeof(CFDataRef)); 609 610 CFDictionaryGetKeysAndValues(dict, keys, values); 611 for (i = 0; i < nElements; i++) { 612 pLists[i] = NULL; 613 if (!_SCSerialize((CFPropertyListRef)values[i], (CFDataRef *)&pLists[i], NULL, NULL)) { 614 goto done; 615 } 616 } 617 } 618 619 newDict = CFDictionaryCreate(NULL, 620 keys, 621 pLists, 622 nElements, 623 &kCFTypeDictionaryKeyCallBacks, 624 &kCFTypeDictionaryValueCallBacks); 625 626 done : 627 628 if (nElements > 0) { 629 for (i = 0; i < nElements; i++) { 630 if (pLists[i] != NULL) CFRelease((CFDataRef)pLists[i]); 631 } 632 633 if (keys != keys_q) { 634 CFAllocatorDeallocate(NULL, keys); 635 CFAllocatorDeallocate(NULL, values); 636 CFAllocatorDeallocate(NULL, pLists); 637 } 638 } 639 640 return newDict; 641} 642 643 644CF_RETURNS_RETAINED 645CFDictionaryRef 646_SCUnserializeMultiple(CFDictionaryRef dict) 647{ 648 const void * keys_q[N_QUICK]; 649 const void ** keys = keys_q; 650 CFIndex nElements; 651 CFDictionaryRef newDict = NULL; 652 const void * pLists_q[N_QUICK]; 653 const void ** pLists = pLists_q; 654 const void * values_q[N_QUICK]; 655 const void ** values = values_q; 656 657 nElements = CFDictionaryGetCount(dict); 658 if (nElements > 0) { 659 CFIndex i; 660 661 if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 662 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 663 values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 664 pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 665 } 666 memset(pLists, 0, nElements * sizeof(CFTypeRef)); 667 668 CFDictionaryGetKeysAndValues(dict, keys, values); 669 for (i = 0; i < nElements; i++) { 670 if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, 0)) { 671 goto done; 672 } 673 } 674 } 675 676 newDict = CFDictionaryCreate(NULL, 677 keys, 678 pLists, 679 nElements, 680 &kCFTypeDictionaryKeyCallBacks, 681 &kCFTypeDictionaryValueCallBacks); 682 683 done : 684 685 if (nElements > 0) { 686 CFIndex i; 687 688 for (i = 0; i < nElements; i++) { 689 if (pLists[i]) CFRelease(pLists[i]); 690 } 691 692 if (keys != keys_q) { 693 CFAllocatorDeallocate(NULL, keys); 694 CFAllocatorDeallocate(NULL, values); 695 CFAllocatorDeallocate(NULL, pLists); 696 } 697 } 698 699 return newDict; 700} 701 702 703#pragma mark - 704 705 706CFPropertyListRef 707_SCCreatePropertyListFromResource(CFURLRef url) 708{ 709 CFDictionaryRef dict = NULL; 710 SInt64 fileLen = 0; 711 Boolean ok; 712 CFReadStreamRef readStream; 713 CFNumberRef val = NULL; 714 715 if (!CFURLCopyResourcePropertyForKey(url, kCFURLFileSizeKey, &val, NULL) || 716 (val == NULL)) { 717 // if size not available 718 SC_log(LOG_NOTICE, "CFURLCopyResourcePropertyForKey() size not available: %@", url); 719 return NULL; 720 } 721 722 ok = CFNumberGetValue(val, kCFNumberSInt64Type, &fileLen); 723 CFRelease(val); 724 if (!ok || (fileLen == 0)) { 725 // if empty or size too large 726 SC_log(LOG_INFO, "_SCCreatePropertyListFromResource() improper size: %@", url); 727 return NULL; 728 } 729 730 readStream = CFReadStreamCreateWithFile(NULL, url); 731 if (readStream != NULL) { 732 if (CFReadStreamOpen(readStream)) { 733 UInt8 *buffer; 734 CFIndex dataLen; 735 736 buffer = CFAllocatorAllocate(NULL, (CFIndex)fileLen, 0); 737 dataLen = CFReadStreamRead(readStream, buffer, (CFIndex)fileLen); 738 if (dataLen == (CFIndex)fileLen) { 739 CFDataRef data; 740 741 data = CFDataCreateWithBytesNoCopy(NULL, buffer, (CFIndex)fileLen, kCFAllocatorNull); 742 if (data != NULL) { 743 dict = CFPropertyListCreateWithData(NULL, 744 data, 745 kCFPropertyListImmutable, 746 NULL, 747 NULL); 748 CFRelease(data); 749 } 750 } 751 CFAllocatorDeallocate(NULL, buffer); 752 CFReadStreamClose(readStream); 753 } 754 CFRelease(readStream); 755 } 756 757 return dict; 758} 759 760 761#pragma mark - 762#pragma mark CFRunLoop scheduling 763 764 765__private_extern__ void 766_SC_signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList) 767{ 768 CFRunLoopRef rl = NULL; 769 CFRunLoopRef rl1 = NULL; 770 CFIndex i; 771 CFIndex n = CFArrayGetCount(rlList); 772 773 if (n == 0) { 774 return; 775 } 776 777 /* get first runLoop for this object */ 778 for (i = 0; i < n; i += 3) { 779 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { 780 continue; 781 } 782 783 rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); 784 break; 785 } 786 787 if (rl1 == NULL) { 788 /* if not scheduled */ 789 return; 790 } 791 792 /* check if we have another runLoop for this object */ 793 rl = rl1; 794 for (i = i+3; i < n; i += 3) { 795 CFRunLoopRef rl2; 796 797 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { 798 continue; 799 } 800 801 rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); 802 if (!CFEqual(rl1, rl2)) { 803 /* we've got more than one runLoop */ 804 rl = NULL; 805 break; 806 } 807 } 808 809 if (rl != NULL) { 810 /* if we only have one runLoop */ 811 CFRunLoopWakeUp(rl); 812 return; 813 } 814 815 /* more than one different runLoop, so we must pick one */ 816 for (i = 0; i < n; i+=3) { 817 CFStringRef rlMode; 818 819 if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { 820 continue; 821 } 822 823 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); 824 rlMode = CFRunLoopCopyCurrentMode(rl); 825 if (rlMode != NULL) { 826 Boolean waiting; 827 828 waiting = (CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)); 829 CFRelease(rlMode); 830 if (waiting) { 831 /* we've found a runLoop that's "ready" */ 832 CFRunLoopWakeUp(rl); 833 return; 834 } 835 } 836 } 837 838 /* didn't choose one above, so choose first */ 839 CFRunLoopWakeUp(rl1); 840 return; 841} 842 843 844__private_extern__ Boolean 845_SC_isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) 846{ 847 CFIndex i; 848 CFIndex n = CFArrayGetCount(rlList); 849 850 for (i = 0; i < n; i += 3) { 851 if ((obj != NULL) && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { 852 continue; 853 } 854 if ((runLoop != NULL) && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { 855 continue; 856 } 857 if ((runLoopMode != NULL) && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { 858 continue; 859 } 860 return TRUE; 861 } 862 863 return FALSE; 864} 865 866 867__private_extern__ void 868_SC_schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) 869{ 870 CFArrayAppendValue(rlList, obj); 871 CFArrayAppendValue(rlList, runLoop); 872 CFArrayAppendValue(rlList, runLoopMode); 873 874 return; 875} 876 877 878__private_extern__ Boolean 879_SC_unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all) 880{ 881 CFIndex i = 0; 882 Boolean found = FALSE; 883 CFIndex n = CFArrayGetCount(rlList); 884 885 while (i < n) { 886 if ((obj != NULL) && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { 887 i += 3; 888 continue; 889 } 890 if ((runLoop != NULL) && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { 891 i += 3; 892 continue; 893 } 894 if ((runLoopMode != NULL) && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { 895 i += 3; 896 continue; 897 } 898 899 found = TRUE; 900 901 CFArrayRemoveValueAtIndex(rlList, i + 2); 902 CFArrayRemoveValueAtIndex(rlList, i + 1); 903 CFArrayRemoveValueAtIndex(rlList, i); 904 905 if (!all) { 906 return found; 907 } 908 909 n -= 3; 910 } 911 912 return found; 913} 914 915 916#pragma mark - 917#pragma mark Bundle 918 919 920#define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration") 921#define SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN (sizeof(SYSTEMCONFIGURATION_FRAMEWORK_PATH) - 1) 922 923#define SUFFIX_SYM "~sym" 924#define SUFFIX_SYM_LEN (sizeof(SUFFIX_SYM) - 1) 925 926#define SUFFIX_DST "~dst" 927 928 929CFBundleRef 930_SC_CFBundleGet(void) 931{ 932 static CFBundleRef bundle = NULL; 933 char *env; 934 size_t len; 935 CFURLRef url; 936 937 if (bundle != NULL) { 938 goto done; 939 } 940 941 bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID); 942 if (bundle != NULL) { 943 CFRetain(bundle); // we want to hold a reference to the bundle 944 goto done; 945 } else { 946 SC_log(LOG_NOTICE, "could not get CFBundle for \"%@\". Trying harder...", 947 SYSTEMCONFIGURATION_BUNDLE_ID); 948 } 949 950 // if appropriate (e.g. when debugging), try a bit harder 951 952 env = getenv("DYLD_FRAMEWORK_PATH"); 953 len = (env != NULL) ? strlen(env) : 0; 954 955 if (len > 0) { /* We are debugging */ 956 957 // trim any trailing slashes 958 while (len > 1) { 959 if (env[len - 1] != '/') { 960 break; 961 } 962 len--; 963 } 964 965 // if DYLD_FRAMEWORK_PATH is ".../xxx~sym" than try ".../xxx~dst" 966 if ((len > SUFFIX_SYM_LEN) && 967 (strncmp(&env[len - SUFFIX_SYM_LEN], SUFFIX_SYM, SUFFIX_SYM_LEN) == 0) && 968 ((len + SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN) < MAXPATHLEN)) { 969 char path[MAXPATHLEN]; 970 971 strlcpy(path, env, sizeof(path)); 972 strlcpy(&path[len - SUFFIX_SYM_LEN], SUFFIX_DST, sizeof(path) - (len - SUFFIX_SYM_LEN)); 973 strlcat(&path[len], SYSTEMCONFIGURATION_FRAMEWORK_PATH, sizeof(path) - len); 974 975 url = CFURLCreateFromFileSystemRepresentation(NULL, 976 (UInt8 *)path, 977 len + SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN, 978 TRUE); 979 bundle = CFBundleCreate(NULL, url); 980 CFRelease(url); 981 } 982 } 983 984 if (bundle == NULL) { /* Try a more "direct" route to get the bundle */ 985 986 url = CFURLCreateWithFileSystemPath(NULL, 987 CFSTR(SYSTEMCONFIGURATION_FRAMEWORK_PATH), 988 kCFURLPOSIXPathStyle, 989 TRUE); 990 991 bundle = CFBundleCreate(NULL, url); 992 CFRelease(url); 993 } 994 995 if (bundle == NULL) { 996 SC_log(LOG_ERR, "could not get CFBundle for \"%@\"", SYSTEMCONFIGURATION_BUNDLE_ID); 997 } 998 999done: 1000 return bundle; 1001} 1002 1003 1004/* 1005 * cachedInfo 1006 * <dict> 1007 * <key>bundleID-tableName</key> 1008 * <dict> 1009 * ... property list from non-localized bundle URL 1010 * </dict> 1011 * </dict> 1012 */ 1013static CFMutableDictionaryRef cachedInfo = NULL; 1014 1015 1016static dispatch_queue_t 1017_SC_CFBundleCachedInfoQueue() 1018{ 1019 static dispatch_once_t once; 1020 static dispatch_queue_t q; 1021 1022 dispatch_once(&once, ^{ 1023 q = dispatch_queue_create("_SC_CFBundleCachedInfo", NULL); 1024 }); 1025 1026 return q; 1027} 1028 1029 1030static CFStringRef 1031_SC_CFBundleCachedInfoCopyTableKey(CFBundleRef bundle, CFStringRef tableName) 1032{ 1033 CFStringRef bundleID; 1034 CFStringRef tableKey; 1035 1036 bundleID = CFBundleGetIdentifier(bundle); 1037 tableKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@: %@"), bundleID, tableName); 1038 return tableKey; 1039} 1040 1041 1042static CFDictionaryRef 1043_SC_CFBundleCachedInfoCopyTable(CFBundleRef bundle, CFStringRef tableName) 1044{ 1045 __block CFDictionaryRef dict = NULL; 1046 1047 dispatch_sync(_SC_CFBundleCachedInfoQueue(), ^{ 1048 if (cachedInfo != NULL) { 1049 CFStringRef tableKey; 1050 1051 tableKey = _SC_CFBundleCachedInfoCopyTableKey(bundle, tableName); 1052 dict = CFDictionaryGetValue(cachedInfo, tableKey); 1053 if (dict != NULL) { 1054 CFRetain(dict); 1055 } 1056 CFRelease(tableKey); 1057 } 1058 }); 1059 1060 return dict; 1061} 1062 1063 1064static void 1065_SC_CFBundleCachedInfoSaveTable(CFBundleRef bundle, CFStringRef tableName, CFDictionaryRef table) 1066{ 1067 1068 dispatch_sync(_SC_CFBundleCachedInfoQueue(), ^{ 1069 CFStringRef tableKey; 1070 1071 tableKey = _SC_CFBundleCachedInfoCopyTableKey(bundle, tableName); 1072 SC_log(LOG_DEBUG, "Caching %@", tableKey); 1073 1074 if (cachedInfo == NULL) { 1075 cachedInfo = CFDictionaryCreateMutable(NULL, 1076 0, 1077 &kCFTypeDictionaryKeyCallBacks, 1078 &kCFTypeDictionaryValueCallBacks); 1079 } 1080 CFDictionarySetValue(cachedInfo, tableKey, table); 1081 CFRelease(tableKey); 1082 }); 1083 1084 return; 1085} 1086 1087 1088CFStringRef 1089_SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) 1090{ 1091 CFStringRef str = NULL; 1092 CFDictionaryRef table = NULL; 1093 CFURLRef url; 1094 1095 if ((tableName == NULL) || CFEqual(tableName, CFSTR(""))) { 1096 tableName = CFSTR("Localizable"); 1097 } 1098 1099 table = _SC_CFBundleCachedInfoCopyTable(bundle, tableName); 1100 if (table == NULL) { 1101 url = CFBundleCopyResourceURLForLocalization(bundle, 1102 tableName, 1103 CFSTR("strings"), 1104 NULL, 1105 CFSTR("en")); 1106 if (url != NULL) { 1107 table = _SCCreatePropertyListFromResource(url); 1108 CFRelease(url); 1109 if (table != NULL) { 1110 _SC_CFBundleCachedInfoSaveTable(bundle, tableName, table); 1111 } 1112 } else { 1113 SC_log(LOG_ERR, "failed to get resource url: {bundle:%@, table: %@}", bundle, tableName); 1114 } 1115 } 1116 1117 if (table != NULL) { 1118 if (isA_CFDictionary(table)) { 1119 str = CFDictionaryGetValue(table, key); 1120 if (str != NULL) { 1121 CFRetain(str); 1122 } 1123 } 1124 1125 CFRelease(table); 1126 } 1127 1128 if (str == NULL) { 1129 str = CFRetain(value); 1130 } 1131 1132 return str; 1133} 1134 1135 1136#pragma mark - 1137#pragma mark Mach port / CFMachPort management 1138 1139 1140CFMachPortRef 1141_SC_CFMachPortCreateWithPort(const char *portDescription, 1142 mach_port_t portNum, 1143 CFMachPortCallBack callout, 1144 CFMachPortContext *context) 1145{ 1146 CFMachPortRef port; 1147 Boolean shouldFree = FALSE; 1148 1149 port = CFMachPortCreateWithPort(NULL, portNum, callout, context, &shouldFree); 1150 if ((port == NULL) || shouldFree) { 1151 char *crash_info; 1152 CFStringRef err; 1153 1154 SC_log(LOG_NOTICE, "%s: CFMachPortCreateWithPort() failed , port = %p", 1155 portDescription, 1156 (void *)(uintptr_t)portNum); 1157 if (port != NULL) { 1158 err = CFStringCreateWithFormat(NULL, NULL, 1159 CFSTR("%s: CFMachPortCreateWithPort recycled, [old] port = %@"), 1160 portDescription, port); 1161 } else { 1162 err = CFStringCreateWithFormat(NULL, NULL, 1163 CFSTR("%s: CFMachPortCreateWithPort returned NULL"), 1164 portDescription); 1165 } 1166 crash_info = _SC_cfstring_to_cstring(err, NULL, 0, kCFStringEncodingASCII); 1167 CFRelease(err); 1168 1169 err = CFStringCreateWithFormat(NULL, 1170 NULL, 1171 CFSTR("A recycled mach_port has been detected by \"%s\"."), 1172 getprogname()); 1173 _SC_crash(crash_info, CFSTR("CFMachPort error"), err); 1174 CFAllocatorDeallocate(NULL, crash_info); 1175 CFRelease(err); 1176 } 1177 1178 return port; 1179} 1180 1181 1182#pragma mark - 1183#pragma mark DOS encoding/codepage 1184 1185 1186#if !TARGET_OS_IPHONE 1187void 1188_SC_dos_encoding_and_codepage(CFStringEncoding macEncoding, 1189 UInt32 macRegion, 1190 CFStringEncoding *dosEncoding, 1191 UInt32 *dosCodepage) 1192{ 1193 switch (macEncoding) { 1194 case kCFStringEncodingMacRoman: 1195 if (macRegion != 0) /* anything non-zero is not US */ 1196 *dosEncoding = kCFStringEncodingDOSLatin1; 1197 else /* US region */ 1198 *dosEncoding = kCFStringEncodingDOSLatinUS; 1199 break; 1200 1201 case kCFStringEncodingMacJapanese: 1202 *dosEncoding = kCFStringEncodingDOSJapanese; 1203 break; 1204 1205 case kCFStringEncodingMacChineseTrad: 1206 *dosEncoding = kCFStringEncodingDOSChineseTrad; 1207 break; 1208 1209 case kCFStringEncodingMacKorean: 1210 *dosEncoding = kCFStringEncodingDOSKorean; 1211 break; 1212 1213 case kCFStringEncodingMacArabic: 1214 *dosEncoding = kCFStringEncodingDOSArabic; 1215 break; 1216 1217 case kCFStringEncodingMacHebrew: 1218 *dosEncoding = kCFStringEncodingDOSHebrew; 1219 break; 1220 1221 case kCFStringEncodingMacGreek: 1222 *dosEncoding = kCFStringEncodingDOSGreek; 1223 break; 1224 1225 case kCFStringEncodingMacCyrillic: 1226 *dosEncoding = kCFStringEncodingDOSCyrillic; 1227 break; 1228 1229 case kCFStringEncodingMacThai: 1230 *dosEncoding = kCFStringEncodingDOSThai; 1231 break; 1232 1233 case kCFStringEncodingMacChineseSimp: 1234 *dosEncoding = kCFStringEncodingDOSChineseSimplif; 1235 break; 1236 1237 case kCFStringEncodingMacCentralEurRoman: 1238 *dosEncoding = kCFStringEncodingDOSLatin2; 1239 break; 1240 1241 case kCFStringEncodingMacTurkish: 1242 *dosEncoding = kCFStringEncodingDOSTurkish; 1243 break; 1244 1245 case kCFStringEncodingMacCroatian: 1246 *dosEncoding = kCFStringEncodingDOSLatin2; 1247 break; 1248 1249 case kCFStringEncodingMacIcelandic: 1250 *dosEncoding = kCFStringEncodingDOSIcelandic; 1251 break; 1252 1253 case kCFStringEncodingMacRomanian: 1254 *dosEncoding = kCFStringEncodingDOSLatin2; 1255 break; 1256 1257 case kCFStringEncodingMacFarsi: 1258 *dosEncoding = kCFStringEncodingDOSArabic; 1259 break; 1260 1261 case kCFStringEncodingMacUkrainian: 1262 *dosEncoding = kCFStringEncodingDOSCyrillic; 1263 break; 1264 1265 default: 1266 *dosEncoding = kCFStringEncodingDOSLatin1; 1267 break; 1268 } 1269 1270 *dosCodepage = CFStringConvertEncodingToWindowsCodepage(*dosEncoding); 1271 return; 1272} 1273#endif // !TARGET_OS_IPHONE 1274 1275 1276#pragma mark - 1277#pragma mark Debugging 1278 1279 1280/* 1281 * print status of in-use mach ports 1282 */ 1283void 1284_SC_logMachPortStatus(void) 1285{ 1286 kern_return_t status; 1287 mach_port_name_array_t ports; 1288 mach_port_type_array_t types; 1289 mach_msg_type_number_t pi, pn, tn; 1290 CFMutableStringRef str; 1291 1292 SC_log(LOG_DEBUG, "----------"); 1293 1294 /* report on ALL mach ports associated with this task */ 1295 status = mach_port_names(mach_task_self(), &ports, &pn, &types, &tn); 1296 if (status == MACH_MSG_SUCCESS) { 1297 str = CFStringCreateMutable(NULL, 0); 1298 for (pi = 0; pi < pn; pi++) { 1299 char rights[16], *rp = &rights[0]; 1300 1301 if (types[pi] != MACH_PORT_TYPE_NONE) { 1302 *rp++ = ' '; 1303 *rp++ = '('; 1304 if (types[pi] & MACH_PORT_TYPE_SEND) 1305 *rp++ = 'S'; 1306 if (types[pi] & MACH_PORT_TYPE_RECEIVE) 1307 *rp++ = 'R'; 1308 if (types[pi] & MACH_PORT_TYPE_SEND_ONCE) 1309 *rp++ = 'O'; 1310 if (types[pi] & MACH_PORT_TYPE_PORT_SET) 1311 *rp++ = 'P'; 1312 if (types[pi] & MACH_PORT_TYPE_DEAD_NAME) 1313 *rp++ = 'D'; 1314 *rp++ = ')'; 1315 } 1316 *rp = '\0'; 1317 CFStringAppendFormat(str, NULL, CFSTR(" %d%s"), ports[pi], rights); 1318 } 1319 SC_log(LOG_DEBUG, "Task ports (n=%d):%@", pn, str); 1320 CFRelease(str); 1321 } 1322 1323 return; 1324} 1325 1326 1327__private_extern__ 1328kern_return_t 1329_SC_getMachPortReferences(mach_port_t port, 1330 mach_port_type_t *pt, 1331 mach_port_urefs_t *refs_send, 1332 mach_port_urefs_t *refs_recv, 1333 mach_port_status_t *recv_status, 1334 mach_port_urefs_t *refs_once, 1335 mach_port_urefs_t *refs_pset, 1336 mach_port_urefs_t *refs_dead, 1337 const char *err_prefix) 1338{ 1339 kern_return_t status; 1340 1341 status = mach_port_type(mach_task_self(), port, pt); 1342 if (status != KERN_SUCCESS) { 1343 SC_log(LOG_DEBUG, "%smach_port_type(..., 0x%x): %s", 1344 err_prefix, 1345 port, 1346 mach_error_string(status)); 1347 return status; 1348 } 1349 1350 if ((refs_send != NULL) && ((*pt & MACH_PORT_TYPE_SEND) != 0)) { 1351 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, refs_send); 1352 if (status != KERN_SUCCESS) { 1353 SC_log(LOG_DEBUG, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s", 1354 err_prefix, 1355 port, 1356 mach_error_string(status)); 1357 return status; 1358 } 1359 } 1360 1361 if ((refs_recv != NULL) && (recv_status != NULL) && ((*pt & MACH_PORT_TYPE_RECEIVE) != 0)) { 1362 mach_msg_type_number_t count; 1363 1364 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, refs_recv); 1365 if (status != KERN_SUCCESS) { 1366 SC_log(LOG_DEBUG, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_RECEIVE): %s", 1367 err_prefix, 1368 port, 1369 mach_error_string(status)); 1370 return status; 1371 } 1372 1373 count = MACH_PORT_RECEIVE_STATUS_COUNT; 1374 status = mach_port_get_attributes(mach_task_self(), 1375 port, 1376 MACH_PORT_RECEIVE_STATUS, 1377 (mach_port_info_t)recv_status, 1378 &count); 1379 if (status != KERN_SUCCESS) { 1380 SC_log(LOG_DEBUG, "%smach_port_get_attributes(..., 0x%x, MACH_PORT_RECEIVE_STATUS): %s", 1381 err_prefix, 1382 port, 1383 mach_error_string(status)); 1384 return status; 1385 } 1386 } 1387 1388 if ((refs_once != NULL) && ((*pt & MACH_PORT_TYPE_SEND_ONCE) != 0)) { 1389 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND_ONCE, refs_once); 1390 if (status != KERN_SUCCESS) { 1391 SC_log(LOG_DEBUG, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND_ONCE): %s", 1392 err_prefix, 1393 port, 1394 mach_error_string(status)); 1395 return status; 1396 } 1397 } 1398 1399 if ((refs_pset != NULL) && ((*pt & MACH_PORT_TYPE_PORT_SET) != 0)) { 1400 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, refs_pset); 1401 if (status != KERN_SUCCESS) { 1402 SC_log(LOG_DEBUG, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_PORT_SET): %s", 1403 err_prefix, 1404 port, 1405 mach_error_string(status)); 1406 return status; 1407 } 1408 } 1409 1410 if ((refs_dead != NULL) && ((*pt & MACH_PORT_TYPE_DEAD_NAME) != 0)) { 1411 status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_DEAD_NAME, refs_dead); 1412 if (status != KERN_SUCCESS) { 1413 SC_log(LOG_DEBUG, "%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_DEAD_NAME): %s", 1414 err_prefix, 1415 port, 1416 mach_error_string(status)); 1417 return status; 1418 } 1419 } 1420 1421 return KERN_SUCCESS; 1422} 1423 1424 1425void 1426_SC_logMachPortReferences(const char *str, mach_port_t port) 1427{ 1428 const char *blanks = " "; 1429 char buf[60]; 1430 mach_port_type_t pt; 1431 mach_port_status_t recv_status = { .mps_nsrequest = 0, }; 1432 mach_port_urefs_t refs_send = 0; 1433 mach_port_urefs_t refs_recv = 0; 1434 mach_port_urefs_t refs_once = 0; 1435 mach_port_urefs_t refs_pset = 0; 1436 mach_port_urefs_t refs_dead = 0; 1437 kern_return_t status; 1438 1439 buf[0] = '\0'; 1440 if (str != NULL) { 1441 static int is_configd = -1; 1442 1443 if (is_configd == -1) { 1444 is_configd = (strcmp(getprogname(), _SC_SERVER_PROG) == 0); 1445 } 1446 if (is_configd == 1) { 1447 // if "configd", add indication if this is the M[ain] or [P]lugin thread 1448 strlcpy(buf, 1449 (CFRunLoopGetMain() == CFRunLoopGetCurrent()) ? "M " : "P ", 1450 sizeof(buf)); 1451 } 1452 1453 // add provided string 1454 strlcat(buf, str, sizeof(buf)); 1455 1456 // fill 1457 strlcat(buf, blanks, sizeof(buf)); 1458 if (strcmp(&buf[sizeof(buf) - 3], " ") == 0) { 1459 buf[sizeof(buf) - 3] = ':'; 1460 } 1461 } 1462 1463 status = _SC_getMachPortReferences(port, 1464 &pt, 1465 &refs_send, 1466 &refs_recv, 1467 &recv_status, 1468 &refs_once, 1469 &refs_pset, 1470 &refs_dead, 1471 buf); 1472 if (status != KERN_SUCCESS) { 1473 return; 1474 } 1475 1476 SC_log(LOG_DEBUG, "%smach port 0x%x (%d): send=%d, receive=%d, send once=%d, port set=%d, dead name=%d%s%s", 1477 buf, 1478 port, 1479 port, 1480 refs_send, 1481 refs_recv, 1482 refs_once, 1483 refs_pset, 1484 refs_dead, 1485 recv_status.mps_nsrequest ? ", no more senders" : "", 1486 ((pt & MACH_PORT_TYPE_DEAD_NAME) != 0) ? ", dead name request" : ""); 1487 1488 return; 1489} 1490 1491 1492CFStringRef 1493_SC_copyBacktrace() 1494{ 1495 int n; 1496 void *stack[64]; 1497 char **symbols; 1498 CFMutableStringRef trace; 1499 1500 n = backtrace(stack, sizeof(stack)/sizeof(stack[0])); 1501 if (n == -1) { 1502 SC_log(LOG_NOTICE, "backtrace() failed: %s", strerror(errno)); 1503 return NULL; 1504 } 1505 1506 trace = CFStringCreateMutable(NULL, 0); 1507 1508 symbols = backtrace_symbols(stack, n); 1509 if (symbols != NULL) { 1510 int i; 1511 1512 for (i = 0; i < n; i++) { 1513 CFStringAppendFormat(trace, NULL, CFSTR("%s\n"), symbols[i]); 1514 } 1515 1516 free(symbols); 1517 } 1518 1519 return trace; 1520} 1521 1522 1523static void 1524_SC_ReportCrash(CFStringRef notifyHeader, CFStringRef notifyMessage) 1525{ 1526#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 1527#pragma unused(notifyHeader) 1528#pragma unused(notifyMessage) 1529#endif // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 1530 static Boolean warned = FALSE; 1531 1532 if (!warned) { 1533#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 1534 CFStringRef displayMessage; 1535 1536 displayMessage = CFStringCreateWithFormat(NULL, 1537 NULL, 1538 CFSTR("%@\n\nPlease collect the crash report and file a Radar."), 1539 notifyMessage); 1540 CFUserNotificationDisplayNotice(0, 1541 kCFUserNotificationStopAlertLevel, 1542 NULL, 1543 NULL, 1544 NULL, 1545 notifyHeader, 1546 displayMessage, 1547 NULL); 1548 CFRelease(displayMessage); 1549#endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 1550 warned = TRUE; 1551 } 1552 1553 return; 1554} 1555 1556 1557void 1558_SC_crash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMessage) 1559{ 1560 if (_SC_isAppleInternal()) { 1561 if (crash_info != NULL) { 1562 CRSetCrashLogMessage(crash_info); 1563 SC_log(LOG_NOTICE, "%s", crash_info); 1564 } 1565 1566 // simulate a crash report 1567 os_log_with_type(SC_LOG_HANDLE(), OS_LOG_TYPE_FAULT, "%s", crash_info); 1568 1569 // report the crash to the user 1570 if ((notifyHeader != NULL) && (notifyMessage != NULL)) { 1571 _SC_ReportCrash(notifyHeader, notifyMessage); 1572 } 1573 1574 if (crash_info != NULL) { 1575 CRSetCrashLogMessage(NULL); 1576 } 1577 } 1578 1579 return; 1580} 1581 1582 1583Boolean 1584_SC_getconninfo(int socket, struct sockaddr_storage *src_addr, struct sockaddr_storage *dest_addr, int *if_index, uint32_t *flags) 1585{ 1586 struct so_cinforeq request; 1587 1588 memset(&request, 0, sizeof(request)); 1589 1590 if (src_addr != NULL) { 1591 memset(src_addr, 0, sizeof(*src_addr)); 1592 request.scir_src = (struct sockaddr *)src_addr; 1593 request.scir_src_len = sizeof(*src_addr); 1594 } 1595 1596 if (dest_addr != NULL) { 1597 memset(dest_addr, 0, sizeof(*dest_addr)); 1598 request.scir_dst = (struct sockaddr *)dest_addr; 1599 request.scir_dst_len = sizeof(*dest_addr); 1600 } 1601 1602 if (ioctl(socket, SIOCGCONNINFO, &request) != 0) { 1603 SC_log(LOG_NOTICE, "SIOCGCONNINFO failed: %s", strerror(errno)); 1604 return FALSE; 1605 } 1606 1607 if (if_index != NULL) { 1608 *if_index = 0; 1609 *if_index = request.scir_ifindex; 1610 } 1611 1612 if (flags != NULL) { 1613 *flags = 0; 1614 *flags = request.scir_flags; 1615 } 1616 1617 return TRUE; 1618}