2 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 1998-2012, Apple Inc. All rights reserved.
26 Responsibility: Tony Parker
29 #include <CoreFoundation/CFPriv.h>
30 #include "CFInternal.h"
31 #include "CFLocaleInternal.h"
32 #include <CoreFoundation/CFPriv.h>
33 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
34 #include <CoreFoundation/CFBundle.h>
36 #include <CoreFoundation/CFURLAccess.h>
37 #include <CoreFoundation/CFPropertyList.h>
38 #include <CoreFoundation/CFTimeZone.h>
39 #include <CoreFoundation/CFCalendar.h>
40 #if DEPLOYMENT_TARGET_WINDOWS
47 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
50 #define ASL_LEVEL_EMERG 0
51 #define ASL_LEVEL_DEBUG 7
54 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
57 #include <mach/mach.h>
59 #include <mach-o/loader.h>
60 #include <mach-o/dyld.h>
61 #include <crt_externs.h>
64 #include <vproc_priv.h>
65 #include <sys/sysctl.h>
67 #include <mach/mach.h>
68 #include <mach/mach_vm.h>
71 #include <sys/errno.h>
72 #include <mach/mach_time.h>
75 #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
80 /* Comparator is passed the address of the values. */
81 /* Binary searches a sorted-increasing array of some type.
82 Return value is either 1) the index of the element desired,
83 if the target value exists in the list, 2) greater than or
84 equal to count, if the element is greater than all the values
85 in the list, or 3) the index of the element greater than the
88 For example, a search in the list of integers:
98 For instance, if you just care about found/not found:
99 index = CFBSearch(list, count, elem);
100 if (count <= index || list[index] != elem) {
107 __private_extern__ CFIndex
CFBSearch(const void *element
, CFIndex elementSize
, const void *list
, CFIndex count
, CFComparatorFunction comparator
, void *context
) {
108 const char *ptr
= (const char *)list
;
110 CFIndex half
= count
/ 2;
111 const char *probe
= ptr
+ elementSize
* half
;
112 CFComparisonResult cr
= comparator(element
, probe
, context
);
113 if (0 == cr
) return (probe
- (const char *)list
) / elementSize
;
114 ptr
= (cr
< 0) ? ptr
: probe
+ elementSize
;
115 count
= (cr
< 0) ? half
: (half
+ (count
& 1) - 1);
117 return (ptr
- (const char *)list
) / elementSize
;
121 #define ELF_STEP(B) T1 = (H << 4) + B; T2 = T1 & 0xF0000000; if (T2) T1 ^= (T2 >> 24); T1 &= (~T2); H = T1;
123 CFHashCode
CFHashBytes(uint8_t *bytes
, CFIndex length
) {
124 /* The ELF hash algorithm, used in the ELF object file format */
125 UInt32 H
= 0, T1
, T2
;
128 ELF_STEP(bytes
[length
- rem
]);
129 ELF_STEP(bytes
[length
- rem
+ 1]);
130 ELF_STEP(bytes
[length
- rem
+ 2]);
131 ELF_STEP(bytes
[length
- rem
+ 3]);
135 case 3: ELF_STEP(bytes
[length
- 3]);
136 case 2: ELF_STEP(bytes
[length
- 2]);
137 case 1: ELF_STEP(bytes
[length
- 1]);
146 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
147 __private_extern__
uintptr_t __CFFindPointer(uintptr_t ptr
, uintptr_t start
) {
148 vm_map_t task
= mach_task_self();
149 mach_vm_address_t address
= start
;
151 mach_vm_size_t size
= 0;
152 vm_region_basic_info_data_64_t info
;
153 mach_msg_type_number_t count
= VM_REGION_BASIC_INFO_COUNT_64
;
154 mach_port_t object_name
;
155 kern_return_t ret
= mach_vm_region(task
, &address
, &size
, VM_REGION_BASIC_INFO_64
, (vm_region_info_t
)&info
, &count
, &object_name
);
156 if (KERN_SUCCESS
!= ret
) break;
157 boolean_t scan
= (info
.protection
& VM_PROT_WRITE
) ? 1 : 0;
159 uintptr_t *addr
= (uintptr_t *)((uintptr_t)address
);
160 uintptr_t *end
= (uintptr_t *)((uintptr_t)address
+ (uintptr_t)size
);
162 if ((uintptr_t *)start
<= addr
&& *addr
== ptr
) {
163 return (uintptr_t)addr
;
173 __private_extern__
void __CFDumpAllPointerLocations(uintptr_t ptr
) {
176 addr
= __CFFindPointer(ptr
, sizeof(void *) + addr
);
177 printf("%p\n", (void *)addr
);
182 #if DEPLOYMENT_TARGET_WINDOWS
188 static unsigned __stdcall
__CFWinThreadFunc(void *arg
) {
189 struct _args
*args
= (struct _args
*)arg
;
190 ((void (*)(void *))args
->func
)(args
->arg
);
191 CloseHandle(args
->handle
);
192 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, arg
);
198 __private_extern__
void *__CFStartSimpleThread(void *func
, void *arg
) {
199 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
202 pthread_attr_init(&attr
);
203 pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
);
204 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
205 pthread_attr_setstacksize(&attr
, 60 * 1024); // 60K stack for our internal threads is sufficient
206 OSMemoryBarrier(); // ensure arg is fully initialized and set in memory
207 pthread_create(&tid
, &attr
, func
, arg
);
208 pthread_attr_destroy(&attr
);
209 //warning CF: we dont actually know that a pthread_t is the same size as void *
211 #elif DEPLOYMENT_TARGET_WINDOWS
213 struct _args
*args
= (struct _args
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(struct _args
), 0);
214 if (__CFOASafe
) __CFSetLastAllocationEventName(args
, "CFUtilities (thread-args)");
218 /* The thread is created suspended, because otherwise there would be a race between the assignment below of the handle field, and it's possible use in the thread func above. */
219 args
->handle
= (HANDLE
)_beginthreadex(NULL
, 0, __CFWinThreadFunc
, args
, CREATE_SUSPENDED
, &tid
);
220 handle
= args
->handle
;
221 ResumeThread(handle
);
227 // Looks for localized version of "nonLocalized" in the SystemVersion bundle
228 // If not found, and returnNonLocalizedFlag == true, will return the non localized string (retained of course), otherwise NULL
229 // If bundlePtr != NULL, will use *bundlePtr and will return the bundle in there; otherwise bundle is created and released
230 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
231 static CFStringRef
_CFCopyLocalizedVersionKey(CFBundleRef
*bundlePtr
, CFStringRef nonLocalized
) {
232 CFStringRef localized
= NULL
;
233 CFBundleRef locBundle
= bundlePtr
? *bundlePtr
: NULL
;
235 CFURLRef url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, CFSTR("/System/Library/CoreServices/SystemVersion.bundle"), kCFURLPOSIXPathStyle
, false);
237 locBundle
= CFBundleCreate(kCFAllocatorSystemDefault
, url
);
242 localized
= CFBundleCopyLocalizedString(locBundle
, nonLocalized
, nonLocalized
, CFSTR("SystemVersion"));
243 if (bundlePtr
) *bundlePtr
= locBundle
; else CFRelease(locBundle
);
245 return localized
? localized
: (CFStringRef
)CFRetain(nonLocalized
);
249 static CFDictionaryRef
_CFCopyVersionDictionary(CFStringRef path
) {
250 CFPropertyListRef plist
= NULL
;
252 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
256 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, path
, kCFURLPOSIXPathStyle
, false);
257 if (url
&& CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault
, url
, &data
, NULL
, NULL
, NULL
)) {
258 plist
= CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, data
, kCFPropertyListMutableContainers
, NULL
);
261 if (url
) CFRelease(url
);
264 CFBundleRef locBundle
= NULL
;
265 CFStringRef fullVersion
, vers
, versExtra
, build
;
266 CFStringRef versionString
= _CFCopyLocalizedVersionKey(&locBundle
, _kCFSystemVersionProductVersionStringKey
);
267 CFStringRef buildString
= _CFCopyLocalizedVersionKey(&locBundle
, _kCFSystemVersionBuildStringKey
);
268 CFStringRef fullVersionString
= _CFCopyLocalizedVersionKey(&locBundle
, CFSTR("FullVersionString"));
269 if (locBundle
) CFRelease(locBundle
);
271 // Now build the full version string
272 if (CFEqual(fullVersionString
, CFSTR("FullVersionString"))) {
273 CFRelease(fullVersionString
);
274 fullVersionString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@ %%@ (%@ %%@)"), versionString
, buildString
);
276 vers
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionProductVersionKey
);
277 versExtra
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionProductVersionExtraKey
);
278 if (vers
&& versExtra
) vers
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@ %@"), vers
, versExtra
);
279 build
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionBuildVersionKey
);
280 fullVersion
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, fullVersionString
, (vers
? vers
: CFSTR("?")), build
? build
: CFSTR("?"));
281 if (vers
&& versExtra
) CFRelease(vers
);
283 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductVersionStringKey
, versionString
);
284 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionBuildStringKey
, buildString
);
285 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, CFSTR("FullVersionString"), fullVersion
);
286 CFRelease(versionString
);
287 CFRelease(buildString
);
288 CFRelease(fullVersionString
);
289 CFRelease(fullVersion
);
291 #elif DEPLOYMENT_TARGET_WINDOWS
292 OSVERSIONINFOEX osvi
;
293 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
294 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
295 BOOL result
= GetVersionEx((OSVERSIONINFO
*)&osvi
);
296 if (!result
) return NULL
;
298 plist
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 10, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
301 CFStringRef versionString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%ld.%ld(%ld,%ld)"), osvi
.dwMajorVersion
, osvi
.dwMinorVersion
, osvi
.wServicePackMajor
, osvi
.wServicePackMinor
);
304 CFStringRef buildString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%ld"), osvi
.dwBuildNumber
);
306 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductVersionKey
, versionString
);
307 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionBuildVersionKey
, buildString
);
308 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductNameKey
, CFSTR("Windows")); // hard coded for now
310 CFRelease(versionString
);
311 CFRelease(buildString
);
313 return (CFDictionaryRef
)plist
;
316 CFStringRef
CFCopySystemVersionString(void) {
317 CFStringRef versionString
;
318 CFDictionaryRef dict
= _CFCopyServerVersionDictionary();
319 if (!dict
) dict
= _CFCopySystemVersionDictionary();
320 if (!dict
) return NULL
;
321 versionString
= (CFStringRef
)CFDictionaryGetValue(dict
, CFSTR("FullVersionString"));
322 if (versionString
) CFRetain(versionString
);
324 return versionString
;
327 // Obsolete: These two functions cache the dictionaries to avoid calling _CFCopyVersionDictionary() more than once per dict desired
328 // In fact, they do not cache any more, because the file can change after
329 // apps are running in some situations, and apps need the new info.
330 // Proper caching and testing to see if the file has changed, without race
331 // conditions, would require semi-convoluted use of fstat().
333 CFDictionaryRef
_CFCopySystemVersionDictionary(void) {
334 CFPropertyListRef plist
= NULL
;
335 plist
= _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/SystemVersion.plist"));
336 return (CFDictionaryRef
)plist
;
339 CFDictionaryRef
_CFCopyServerVersionDictionary(void) {
340 CFPropertyListRef plist
= NULL
;
341 plist
= _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/ServerVersion.plist"));
342 return (CFDictionaryRef
)plist
;
345 CONST_STRING_DECL(_kCFSystemVersionProductNameKey
, "ProductName")
346 CONST_STRING_DECL(_kCFSystemVersionProductCopyrightKey
, "ProductCopyright")
347 CONST_STRING_DECL(_kCFSystemVersionProductVersionKey
, "ProductVersion")
348 CONST_STRING_DECL(_kCFSystemVersionProductVersionExtraKey
, "ProductVersionExtra")
349 CONST_STRING_DECL(_kCFSystemVersionProductUserVisibleVersionKey
, "ProductUserVisibleVersion")
350 CONST_STRING_DECL(_kCFSystemVersionBuildVersionKey
, "ProductBuildVersion")
351 CONST_STRING_DECL(_kCFSystemVersionProductVersionStringKey
, "Version")
352 CONST_STRING_DECL(_kCFSystemVersionBuildStringKey
, "Build")
355 CF_EXPORT Boolean
_CFExecutableLinkedOnOrAfter(CFSystemVersion version
) {
362 #if DEPLOYMENT_TARGET_MACOSX
363 __private_extern__
void *__CFLookupCarbonCoreFunction(const char *name
) {
364 static void *image
= NULL
;
366 image
= dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", RTLD_LAZY
| RTLD_LOCAL
);
370 dyfunc
= dlsym(image
, name
);
376 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
377 __private_extern__
void *__CFLookupCoreServicesInternalFunction(const char *name
) {
378 static void *image
= NULL
;
380 image
= dlopen("/System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal", RTLD_LAZY
| RTLD_LOCAL
);
384 dyfunc
= dlsym(image
, name
);
389 __private_extern__
void *__CFLookupCFNetworkFunction(const char *name
) {
390 static void *image
= NULL
;
392 const char *path
= NULL
;
394 path
= __CFgetenv("CFNETWORK_LIBRARY_PATH");
397 path
= "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
399 image
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
403 dyfunc
= dlsym(image
, name
);
410 #ifndef __CFGetSessionID_defined
412 __private_extern__
uint32_t __CFGetSessionID(void) {
418 __private_extern__ CFIndex
__CFActiveProcessorCount() {
420 #if DEPLOYMENT_TARGET_WINDOWS
422 GetSystemInfo(&sysInfo
);
423 DWORD_PTR activeProcessorMask
= sysInfo
.dwActiveProcessorMask
;
424 // assumes sizeof(DWORD_PTR) is 64 bits or less
425 uint64_t v
= activeProcessorMask
;
426 v
= v
- ((v
>> 1) & 0x5555555555555555ULL
);
427 v
= (v
& 0x3333333333333333ULL
) + ((v
>> 2) & 0x3333333333333333ULL
);
428 v
= (v
+ (v
>> 4)) & 0xf0f0f0f0f0f0f0fULL
;
429 pcnt
= (v
* 0x0101010101010101ULL
) >> ((sizeof(v
) - 1) * 8);
430 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
431 int32_t mib
[] = {CTL_HW
, HW_AVAILCPU
};
432 size_t len
= sizeof(pcnt
);
433 int32_t result
= sysctl(mib
, sizeof(mib
) / sizeof(int32_t), &pcnt
, &len
, NULL
, 0);
444 __private_extern__
void __CFGetUGIDs(uid_t
*euid
, gid_t
*egid
) {
445 #if 1 && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
448 if (0 == pthread_getugid_np(&uid
, &gid
)) {
449 if (euid
) *euid
= uid
;
450 if (egid
) *egid
= gid
;
454 if (euid
) *euid
= geteuid();
455 if (egid
) *egid
= getegid();
459 const char *_CFPrintForDebugger(const void *obj
) {
460 static char *result
= NULL
;
464 free(result
); // Let go of result from previous call.
467 if (CFGetTypeID(obj
) == CFStringGetTypeID()) {
468 // Makes Ali marginally happier
469 str
= __CFCopyFormattingDescription(obj
, NULL
);
470 if (!str
) str
= CFCopyDescription(obj
);
472 str
= CFCopyDescription(obj
);
475 str
= (CFStringRef
)CFRetain(CFSTR("(null)"));
479 CFStringGetBytes(str
, CFRangeMake(0, CFStringGetLength(str
)), kCFStringEncodingUTF8
, 0, FALSE
, NULL
, 0, &cnt
);
481 result
= (char *) malloc(cnt
+ 2); // 1 for '\0', 1 for an optional '\n'
483 CFStringGetBytes(str
, CFRangeMake(0, CFStringGetLength(str
)), kCFStringEncodingUTF8
, 0, FALSE
, (UInt8
*) result
, cnt
, &cnt
);
487 if (str
) CFRelease(str
);
491 static void _CFShowToFile(FILE *file
, Boolean flush
, const void *obj
) {
494 CFStringInlineBuffer buffer
;
498 if (CFGetTypeID(obj
) == CFStringGetTypeID()) {
499 // Makes Ali marginally happier
500 str
= __CFCopyFormattingDescription(obj
, NULL
);
501 if (!str
) str
= CFCopyDescription(obj
);
503 str
= CFCopyDescription(obj
);
506 str
= (CFStringRef
)CFRetain(CFSTR("(null)"));
508 cnt
= CFStringGetLength(str
);
510 #if DEPLOYMENT_TARGET_WINDOWS
511 UniChar
*ptr
= (UniChar
*)CFStringGetCharactersPtr(str
);
512 BOOL freePtr
= false;
514 CFIndex strLen
= CFStringGetLength(str
);
515 // +2, 1 for newline, 1 for null
516 CFIndex bufSize
= sizeof(UniChar
*) * (CFStringGetMaximumSizeForEncoding(strLen
, kCFStringEncodingUnicode
) + 2);
517 CFIndex bytesUsed
= 0;
518 ptr
= (UniChar
*)malloc(bufSize
);
519 CFStringGetCharacters(str
, CFRangeMake(0, strLen
), ptr
);
524 OutputDebugStringW((wchar_t *)ptr
);
525 if (freePtr
) free(ptr
);
527 CFStringInitInlineBuffer(str
, &buffer
, CFRangeMake(0, cnt
));
528 for (idx
= 0; idx
< cnt
; idx
++) {
529 UniChar ch
= __CFStringGetCharacterFromInlineBufferQuick(&buffer
, idx
);
531 fprintf_l(file
, NULL
, "%c", ch
);
532 lastNL
= (ch
== '\n');
534 fprintf_l(file
, NULL
, "\\u%04x", ch
);
538 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
539 fprintf_l(file
, NULL
, "\n");
541 fprintf(file
, NULL
, "\n");
543 if (flush
) fflush(file
);
547 if (str
) CFRelease(str
);
550 void CFShow(const void *obj
) {
551 _CFShowToFile(stderr
, true, obj
);
555 // message must be a UTF8-encoded, null-terminated, byte buffer with at least length bytes
556 typedef void (*CFLogFunc
)(int32_t lev
, const char *message
, size_t length
, char withBanner
);
558 static Boolean
also_do_stderr() {
559 #if DEPLOYMENT_TARGET_EMBEDDED_MINI
560 // just log to stderr, other logging facilities are out
562 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
563 if (!issetugid() && __CFgetenv("CFLOG_FORCE_STDERR")) {
567 int ret
= fstat(STDERR_FILENO
, &sb
);
568 if (ret
< 0) return false;
569 mode_t m
= sb
.st_mode
& S_IFMT
;
570 if (S_IFREG
== m
|| S_IFSOCK
== m
) return true;
571 if (!(S_IFIFO
== m
|| S_IFCHR
== m
)) return false; // disallow any whacky stuff
572 // if it could be a pipe back to launchd, fail
574 // assumes val is not written to on error
575 vproc_swap_integer(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
576 if (val
) return false;
581 extern char *__CFBundleMainID
;
583 static void __CFLogCString(int32_t lev
, const char *message
, size_t length
, char withBanner
) {
588 #if DEPLOYMENT_TARGET_WINDOWS
591 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
592 // The banner path may use CF functions, but the rest of this function should not. It may be called at times when CF is not fully setup or torn down.
594 CFAbsoluteTime at
= CFAbsoluteTimeGetCurrent();
595 CFCalendarRef calendar
= CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault
, kCFCalendarIdentifierGregorian
);
596 if (!calendar
) goto after_banner
;
597 CFTimeZoneRef tz
= CFTimeZoneCopySystem();
602 CFCalendarSetTimeZone(calendar
, tz
);
604 int32_t year
, month
, day
, hour
, minute
, second
;
605 Boolean dec
= CFCalendarDecomposeAbsoluteTime(calendar
, at
, "yMdHms", &year
, &month
, &day
, &hour
, &minute
, &second
);
607 if (!dec
) goto after_banner
;
609 int32_t ms
= (int32_t)floor(1000.0 * modf(at
, &atf
));
610 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
611 asprintf(&banner
, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year
, month
, day
, hour
, minute
, second
, ms
, *_CFGetProgname(), getpid(), pthread_mach_thread_np(pthread_self()));
612 asprintf(&thread
, "%x", pthread_mach_thread_np(pthread_self()));
613 #elif DEPLOYMENT_TARGET_WINDOWS
614 bannerLen
= asprintf(&banner
, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year
, month
, day
, hour
, minute
, second
, ms
, *_CFGetProgname(), getpid(), GetCurrentThreadId());
615 asprintf(&thread
, "%x", GetCurrentThreadId());
617 bannerLen
= asprintf(&banner
, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year
, month
, day
, hour
, minute
, second
, ms
, *_CFGetProgname(), getpid(), (unsigned int)pthread_self());
618 asprintf(&thread
, "%x", pthread_self());
620 asprintf(&time
, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year
, month
, day
, hour
, minute
, second
, ms
);
624 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
626 __CFGetUGIDs(&euid
, NULL
);
627 asprintf(&uid
, "%d", euid
);
628 aslclient asl
= asl_open(NULL
, __CFBundleMainID
[0] ? __CFBundleMainID
: "com.apple.console", ASL_OPT_NO_DELAY
);
629 aslmsg msg
= asl_new(ASL_TYPE_MSG
);
630 asl_set(msg
, "CFLog Local Time", time
); // not to be documented, not public API
631 asl_set(msg
, "CFLog Thread", thread
); // not to be documented, not public API
632 asl_set(msg
, "ReadUID", uid
);
633 static const char *levstr
[] = {"0", "1", "2", "3", "4", "5", "6", "7"};
634 asl_set(msg
, ASL_KEY_LEVEL
, levstr
[lev
]);
635 asl_set(msg
, ASL_KEY_MSG
, message
);
640 #endif // DEPLOYMENT_TARGET
642 if (also_do_stderr()) {
643 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
645 v
[0].iov_base
= banner
;
646 v
[0].iov_len
= banner
? strlen(banner
) : 0;
647 v
[1].iov_base
= (char *)message
;
648 v
[1].iov_len
= length
;
649 v
[2].iov_base
= "\n";
650 v
[2].iov_len
= (message
[length
- 1] != '\n') ? 1 : 0;
651 int nv
= (v
[0].iov_base
? 1 : 0) + 1 + (v
[2].iov_len
? 1 : 0);
652 static CFSpinLock_t lock
= CFSpinLockInit
;
654 writev(STDERR_FILENO
, v
[0].iov_base
? v
: v
+ 1, nv
);
655 __CFSpinUnlock(&lock
);
656 #elif DEPLOYMENT_TARGET_WINDOWS
657 size_t bufLen
= bannerLen
+ length
+ 1;
658 char *buf
= (char *)malloc(sizeof(char) * bufLen
);
660 // Copy the banner into the debug string
661 memmove_s(buf
, bufLen
, banner
, bannerLen
);
663 // Copy the message into the debug string
664 strcpy_s(buf
+ bannerLen
, bufLen
- bannerLen
, message
);
666 strcpy_s(buf
, bufLen
, message
);
668 buf
[bufLen
- 1] = '\0';
669 fprintf_s(stderr
, "%s\n", buf
);
670 // This Win32 API call only prints when a debugger is active
671 // OutputDebugStringA(buf);
674 size_t bufLen
= bannerLen
+ length
+ 1;
675 char *buf
= (char *)malloc(sizeof(char) * bufLen
);
677 // Copy the banner into the debug string
678 memmove(buf
, banner
, bannerLen
);
680 // Copy the message into the debug string
681 strncpy(buf
+ bannerLen
, message
, bufLen
- bannerLen
);
683 strncpy(buf
, message
, bufLen
);
685 buf
[bufLen
- 1] = '\0';
686 fprintf(stderr
, "%s\n", buf
);
691 if (thread
) free(thread
);
692 if (time
) free(time
);
693 if (banner
) free(banner
);
697 CF_EXPORT
void _CFLogvEx(CFLogFunc logit
, CFStringRef (*copyDescFunc
)(void *, const void *), CFDictionaryRef formatOptions
, int32_t lev
, CFStringRef format
, va_list args
) {
698 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
699 uintptr_t val
= (uintptr_t)_CFGetTSD(__CFTSDKeyIsInCFLog
);
700 if (3 < val
) return; // allow up to 4 nested invocations
701 _CFSetTSD(__CFTSDKeyIsInCFLog
, (void *)(val
+ 1), NULL
);
703 CFStringRef str
= format
? _CFStringCreateWithFormatAndArgumentsAux(kCFAllocatorSystemDefault
, copyDescFunc
, formatOptions
, (CFStringRef
)format
, args
) : 0;
704 CFIndex blen
= str
? CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8
) + 1 : 0;
705 char *buf
= str
? (char *)malloc(blen
) : 0;
707 Boolean converted
= CFStringGetCString(str
, buf
, blen
, kCFStringEncodingUTF8
);
708 size_t len
= strlen(buf
);
709 // silently ignore 0-length or really large messages, and levels outside the valid range
710 if (converted
&& !(len
<= 0 || (1 << 24) < len
) && !(lev
< ASL_LEVEL_EMERG
|| ASL_LEVEL_DEBUG
< lev
)) {
711 (logit
? logit
: __CFLogCString
)(lev
, buf
, len
, 1);
715 if (str
) CFRelease(str
);
716 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
717 _CFSetTSD(__CFTSDKeyIsInCFLog
, (void *)val
, NULL
);
721 // This CF-only log function uses no CF functionality, so it may be called anywhere within CF - including thread teardown or prior to full CF setup
722 __private_extern__
void _CFLogSimple(int32_t lev
, char *format
, ...) {
724 va_start(args
, format
);
725 char formattedMessage
[1024];
726 int length
= vsnprintf(formattedMessage
, 1024, format
, args
);
728 __CFLogCString(lev
, formattedMessage
, length
, 0);
733 void CFLog(int32_t lev
, CFStringRef format
, ...) {
735 va_start(args
, format
);
736 _CFLogvEx(NULL
, NULL
, NULL
, lev
, format
, args
);
742 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
744 kern_return_t
_CFDiscorporateMemoryAllocate(CFDiscorporateMemory
*hm
, size_t size
, bool purgeable
) {
745 kern_return_t ret
= KERN_SUCCESS
;
746 size
= round_page(size
);
747 if (0 == size
) size
= vm_page_size
;
748 memset(hm
, 0, sizeof(CFDiscorporateMemory
));
749 void *addr
= mmap(0, size
, PROT_READ
| PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, VM_MAKE_TAG(0) | (purgeable
? VM_FLAGS_PURGABLE
: 0), 0);
750 if ((uintptr_t)addr
== -1) {
753 if (KERN_SUCCESS
== ret
) {
754 hm
->address
= (mach_vm_address_t
)(uintptr_t)addr
;
755 hm
->size
= (mach_vm_size_t
)size
;
756 hm
->port
= MACH_PORT_NULL
;
757 hm
->corporeal
= true;
758 hm
->purgeable
= purgeable
;
760 if (KERN_SUCCESS
== ret
) ret
= mach_make_memory_entry_64(mach_task_self(), &hm
->size
, hm
->address
, VM_PROT_DEFAULT
, &hm
->port
, MACH_PORT_NULL
);
761 if (KERN_SUCCESS
== ret
) hm
->corporeal
= true;
765 kern_return_t
_CFDiscorporateMemoryDeallocate(CFDiscorporateMemory
*hm
) {
766 kern_return_t ret1
= KERN_SUCCESS
, ret2
= KERN_SUCCESS
;
767 if (hm
->corporeal
) ret1
= mach_vm_deallocate(mach_task_self(), hm
->address
, hm
->size
);
768 hm
->address
= MACH_VM_MIN_ADDRESS
;
769 hm
->corporeal
= false;
770 ret2
= mach_port_deallocate(mach_task_self(), hm
->port
);
771 hm
->port
= MACH_PORT_NULL
;
772 return ret1
!= KERN_SUCCESS
? ret1
: ret2
;
775 kern_return_t
_CFDiscorporateMemoryDematerialize(CFDiscorporateMemory
*hm
) {
776 kern_return_t ret
= KERN_SUCCESS
;
777 if (!hm
->corporeal
) ret
= KERN_INVALID_MEMORY_CONTROL
;
778 int state
= VM_PURGABLE_VOLATILE
;
779 if (KERN_SUCCESS
== ret
) vm_purgable_control(mach_task_self(), (vm_address_t
)hm
->address
, VM_PURGABLE_SET_STATE
, &state
);
780 if (KERN_SUCCESS
== ret
) ret
= mach_vm_deallocate(mach_task_self(), hm
->address
, hm
->size
);
781 if (KERN_SUCCESS
== ret
) hm
->address
= MACH_VM_MIN_ADDRESS
;
782 if (KERN_SUCCESS
== ret
) hm
->corporeal
= false;
786 kern_return_t
_CFDiscorporateMemoryMaterialize(CFDiscorporateMemory
*hm
) {
787 kern_return_t ret
= KERN_SUCCESS
;
788 if (hm
->corporeal
) ret
= KERN_INVALID_MEMORY_CONTROL
;
789 if (KERN_SUCCESS
== ret
) ret
= mach_vm_map(mach_task_self(), &hm
->address
, hm
->size
, 0, VM_FLAGS_ANYWHERE
, hm
->port
, 0, FALSE
, VM_PROT_DEFAULT
, VM_PROT_DEFAULT
, VM_INHERIT_DEFAULT
);
790 if (KERN_SUCCESS
== ret
) hm
->corporeal
= true;
791 int state
= VM_PURGABLE_NONVOLATILE
;
792 if (KERN_SUCCESS
== ret
) ret
= vm_purgable_control(mach_task_self(), (vm_address_t
)hm
->address
, VM_PURGABLE_SET_STATE
, &state
);
793 if (KERN_SUCCESS
== ret
) if (VM_PURGABLE_EMPTY
== state
) ret
= KERN_PROTECTION_FAILURE
; // same as VM_PURGABLE_EMPTY
799 #if DEPLOYMENT_TARGET_MACOSX
801 #define SUDDEN_TERMINATION_ENABLE_VPROC 1
803 #if SUDDEN_TERMINATION_ENABLE_VPROC
805 static CFSpinLock_t __CFProcessKillingLock
= CFSpinLockInit
;
806 static CFIndex __CFProcessKillingDisablingCount
= 1;
807 static Boolean __CFProcessKillingWasTurnedOn
= false;
809 void _CFSuddenTerminationDisable(void) {
810 __CFSpinLock(&__CFProcessKillingLock
);
811 __CFProcessKillingDisablingCount
++;
812 _vproc_transaction_begin();
813 __CFSpinUnlock(&__CFProcessKillingLock
);
816 void _CFSuddenTerminationEnable(void) {
817 // In our model the first call of _CFSuddenTerminationEnable() that does not balance a previous call of _CFSuddenTerminationDisable() actually enables sudden termination so we have to keep a count that's almost redundant with vproc's.
818 __CFSpinLock(&__CFProcessKillingLock
);
819 __CFProcessKillingDisablingCount
--;
820 if (__CFProcessKillingDisablingCount
==0 && !__CFProcessKillingWasTurnedOn
) {
821 _vproc_transactions_enable();
822 __CFProcessKillingWasTurnedOn
= true;
824 // Mail seems to have sudden termination disabling/enabling imbalance bugs that make _vproc_transaction_end() kill the app but we don't want that to prevent our submission of the fix 6382488.
825 if (__CFProcessKillingDisablingCount
>=0) {
826 _vproc_transaction_end();
828 CFLog(kCFLogLevelError
, CFSTR("-[NSProcessInfo enableSuddenTermination] has been invoked more times than necessary to balance invocations of -[NSProcessInfo disableSuddenTermination]. Ignoring."));
831 __CFSpinUnlock(&__CFProcessKillingLock
);
834 void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus
) {
835 // This is for when the caller wants to try to exit quickly if possible but not automatically exit the process when it next becomes clean, because quitting might still be cancelled by the user.
836 __CFSpinLock(&__CFProcessKillingLock
);
837 // Check _vproc_transaction_count() because other code in the process might go straight to the vproc APIs but also check __CFProcessKillingWasTurnedOn because _vproc_transaction_count() can return 0 when transactions didn't even get enabled.
838 if (_vproc_transaction_count()==0 && __CFProcessKillingWasTurnedOn
) {
841 __CFSpinUnlock(&__CFProcessKillingLock
);
844 void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus
) {
845 // The user has had their final opportunity to cancel quitting. Exit as soon as the process is clean. Same carefulness as in _CFSuddenTerminationExitIfTerminationEnabled().
846 __CFSpinLock(&__CFProcessKillingLock
);
847 if (__CFProcessKillingWasTurnedOn
) {
848 _vproc_transaction_try_exit(exitStatus
);
850 __CFSpinUnlock(&__CFProcessKillingLock
);
853 size_t _CFSuddenTerminationDisablingCount(void) {
854 // Until sudden termination has been really enabled vproc's notion of the count is off by one but we can't just return __CFProcessKillingDisablingCount() because that doesn't take into account stuff that calls the vproc_transaction functions behind our back.
855 return _vproc_transaction_count() + (__CFProcessKillingWasTurnedOn
? 0 : 1);
860 #warning Building with vproc sudden termination API disabled.
862 static CFSpinLock_t __CFProcessKillingLock
= CFSpinLockInit
;
863 static size_t __CFProcessKillingDisablingCount
= 1;
864 static Boolean __CFProcessExitNextTimeKillingIsEnabled
= false;
865 static int32_t __CFProcessExitStatus
= 0;
866 static int __CFProcessIsKillableNotifyToken
;
867 static Boolean __CFProcessIsKillableNotifyTokenIsFigured
= false;
869 __private_extern__
void _CFSetSuddenTerminationEnabled(Boolean isEnabled
) {
870 if (!__CFProcessIsKillableNotifyTokenIsFigured
) {
871 char *notificationName
= NULL
;
872 asprintf(¬ificationName
, "com.apple.isKillable.%i", getpid());
873 uint32_t notifyResult
= notify_register_check(notificationName
, &__CFProcessIsKillableNotifyToken
);
874 if (notifyResult
!= NOTIFY_STATUS_OK
) {
875 CFLog(kCFLogLevelError
, CFSTR("%s: notify_register_check() returned %i."), __PRETTY_FUNCTION__
, notifyResult
);
877 free(notificationName
);
878 __CFProcessIsKillableNotifyTokenIsFigured
= true;
880 uint32_t notifyResult
= notify_set_state(__CFProcessIsKillableNotifyToken
, isEnabled
);
881 if (notifyResult
!= NOTIFY_STATUS_OK
) {
882 CFLog(kCFLogLevelError
, CFSTR("%s: notify_set_state() returned %i"), __PRETTY_FUNCTION__
, notifyResult
);
886 void _CFSuddenTerminationDisable(void) {
887 __CFSpinLock(&__CFProcessKillingLock
);
888 if (__CFProcessKillingDisablingCount
== 0) {
889 _CFSetSuddenTerminationEnabled(false);
891 __CFProcessKillingDisablingCount
++;
892 __CFSpinUnlock(&__CFProcessKillingLock
);
895 void _CFSuddenTerminationEnable(void) {
896 __CFSpinLock(&__CFProcessKillingLock
);
897 __CFProcessKillingDisablingCount
--;
898 if (__CFProcessKillingDisablingCount
== 0) {
899 if (__CFProcessExitNextTimeKillingIsEnabled
) {
900 _exit(__CFProcessExitStatus
);
902 _CFSetSuddenTerminationEnabled(true);
905 __CFSpinUnlock(&__CFProcessKillingLock
);
908 void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus
) {
909 __CFSpinLock(&__CFProcessKillingLock
);
910 if (__CFProcessKillingDisablingCount
== 0) {
913 __CFSpinUnlock(&__CFProcessKillingLock
);
916 void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus
) {
917 __CFSpinLock(&__CFProcessKillingLock
);
918 if (__CFProcessKillingDisablingCount
== 0) {
921 __CFProcessExitNextTimeKillingIsEnabled
= YES
;
922 __CFProcessExitStatus
= exitStatus
;
924 __CFSpinUnlock(&__CFProcessKillingLock
);
927 size_t _CFSuddenTerminationDisablingCount(void) {
928 return __CFProcessKillingDisablingCount
;
936 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
938 typedef void (^ThrottleTypeA
)(void); // allows calls per nanoseconds
939 typedef void (^ThrottleTypeB
)(uint64_t amt
); // allows amount per nanoseconds
941 __private_extern__ ThrottleTypeA
__CFCreateThrottleTypeA(uint16_t calls
, uint64_t nanoseconds
) {
942 struct mach_timebase_info info
;
943 mach_timebase_info(&info
);
944 uint64_t period
= nanoseconds
/ info
.numer
* info
.denom
;
946 if (0 == calls
|| 0 == period
) return NULL
;
948 __block OSSpinLock b_lock
= OS_SPINLOCK_INIT
;
949 __block
uint64_t b_values
[calls
];
950 __block
uint64_t *b_oldest
= b_values
;
951 memset(b_values
, 0, sizeof(b_values
));
954 uint64_t curr_time
= mach_absolute_time();
955 OSSpinLockLock(&b_lock
);
956 uint64_t next_time
= *b_oldest
+ period
;
957 *b_oldest
= (curr_time
< next_time
) ? next_time
: curr_time
;
959 if (b_values
+ calls
<= b_oldest
) b_oldest
= b_values
;
960 OSSpinLockUnlock(&b_lock
);
961 if (curr_time
< next_time
) {
962 mach_wait_until(next_time
);
967 __private_extern__ ThrottleTypeB
__CFCreateThrottleTypeB(uint64_t amount
, uint64_t nanoseconds
) {
968 struct mach_timebase_info info
;
969 mach_timebase_info(&info
);
970 uint64_t period
= nanoseconds
/ info
.numer
* info
.denom
;
972 if (0 == amount
|| 0 == period
) return NULL
;
974 __block OSSpinLock b_lock
= OS_SPINLOCK_INIT
;
975 __block
uint64_t b_sum
= 0ULL;
976 __block
uint16_t b_num_values
= 8;
977 __block
uint64_t *b_values
= calloc(b_num_values
, 2 * sizeof(uint64_t));
978 __block
uint64_t *b_oldest
= b_values
;
980 return Block_copy(^(uint64_t amt
){
981 OSSpinLockLock(&b_lock
);
983 OSSpinLockUnlock(&b_lock
);
990 #pragma mark File Reading
992 #include <sys/stat.h>
995 #if DEPLOYMENT_TARGET_WINDOWS
1001 #define open _NS_open
1002 #define stat _NS_stat
1003 #define fstat _fstat
1004 #define statinfo _stat
1006 #define mach_task_self() 0
1009 #define statinfo stat
1012 static CFErrorRef
_CFErrorWithFilePathCodeDomain(CFStringRef domain
, CFIndex code
, CFStringRef path
) {
1013 CFStringRef key
= CFSTR("NSFilePath");
1014 CFDictionaryRef userInfo
= CFDictionaryCreate(kCFAllocatorSystemDefault
, (const void **)&key
, (const void **)&path
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1015 CFErrorRef result
= CFErrorCreate(kCFAllocatorSystemDefault
, domain
, code
, userInfo
);
1016 CFRelease(userInfo
);
1020 // Caller is responsible for freeing memory. munmap() if map == true, else malloc().
1021 __private_extern__ Boolean
_CFReadMappedFromFile(CFStringRef path
, Boolean map
, Boolean uncached
, void **outBytes
, CFIndex
*outLength
, CFErrorRef
*errorPtr
) {
1023 unsigned long length
;
1024 char cpath
[CFMaxPathSize
];
1025 if (!CFStringGetFileSystemRepresentation(path
, cpath
, CFMaxPathSize
)) {
1026 // TODO: real error codes
1027 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainCocoa
, -1, path
);
1031 struct statinfo statBuf
;
1034 fd
= open(cpath
, O_RDONLY
|CF_OPENFLGS
, 0666);
1036 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, errno
, path
);
1039 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1040 if (uncached
) (void)fcntl(fd
, F_NOCACHE
, 1); // Non-zero arg turns off caching; we ignore error as uncached is just a hint
1042 if (fstat(fd
, &statBuf
) < 0) {
1043 int32_t savederrno
= errno
;
1045 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1048 if ((statBuf
.st_mode
& S_IFMT
) != S_IFREG
) {
1050 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, EACCES
, path
);
1053 if (statBuf
.st_size
< 0LL) { // too small
1055 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, ENOMEM
, path
);
1060 if (statBuf
.st_size
> (1LL << 31)) { // refuse to do more than 2GB
1062 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, EFBIG
, path
);
1067 if (0LL == statBuf
.st_size
) {
1068 bytes
= malloc(8); // don't return constant string -- it's freed!
1070 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1072 if((void *)-1 == (bytes
= mmap(0, (size_t)statBuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0))) {
1073 int32_t savederrno
= errno
;
1075 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1078 length
= (unsigned long)statBuf
.st_size
;
1080 bytes
= malloc(statBuf
.st_size
);
1081 if (bytes
== NULL
) {
1083 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, ENOMEM
, path
);
1086 size_t numBytesRemaining
= (size_t)statBuf
.st_size
;
1087 void *readLocation
= bytes
;
1088 while (numBytesRemaining
> 0) {
1089 size_t numBytesRequested
= (numBytesRemaining
< (1LL << 31)) ? numBytesRemaining
: ((1LL << 31) - 1); // This loop is basically a workaround for 4870206
1090 ssize_t numBytesRead
= read(fd
, readLocation
, numBytesRequested
);
1091 if (numBytesRead
<= 0) {
1092 if (numBytesRead
< 0) {
1093 int32_t savederrno
= errno
;
1096 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1100 // This is a bizarre case; 0 bytes read. Might indicate end-of-file?
1104 readLocation
+= numBytesRead
;
1105 numBytesRemaining
-= numBytesRead
;
1108 length
= (unsigned long)statBuf
.st_size
- numBytesRemaining
;
1112 bytes
= malloc(statBuf
.st_size
);
1114 if (!ReadFile((HANDLE
)_get_osfhandle(fd
), bytes
, statBuf
.st_size
, &numBytesRead
, NULL
)) {
1115 DWORD lastError
= GetLastError();
1116 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, lastError
, path
);
1123 length
= numBytesRead
;
1128 *outLength
= length
;