2 * Copyright (c) 2014 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-2014, 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 #if DEPLOYMENT_TARGET_WINDOWS
45 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
48 #define ASL_LEVEL_EMERG 0
49 #define ASL_LEVEL_DEBUG 7
53 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
56 #include <mach/mach.h>
58 #include <mach-o/loader.h>
59 #include <mach-o/dyld.h>
60 #include <crt_externs.h>
63 #include <vproc_priv.h>
64 #include <sys/sysctl.h>
66 #include <mach/mach.h>
67 #include <mach/mach_vm.h>
70 #include <sys/errno.h>
71 #include <mach/mach_time.h>
74 #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 CF_PRIVATE 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 CF_PRIVATE
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 CF_PRIVATE
void __CFDumpAllPointerLocations(uintptr_t ptr
) {
176 addr
= __CFFindPointer(ptr
, sizeof(void *) + addr
);
177 printf("%p\n", (void *)addr
);
182 // Looks for localized version of "nonLocalized" in the SystemVersion bundle
183 // If not found, and returnNonLocalizedFlag == true, will return the non localized string (retained of course), otherwise NULL
184 // If bundlePtr != NULL, will use *bundlePtr and will return the bundle in there; otherwise bundle is created and released
185 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
186 static CFStringRef
_CFCopyLocalizedVersionKey(CFBundleRef
*bundlePtr
, CFStringRef nonLocalized
) {
187 CFStringRef localized
= NULL
;
188 CFBundleRef locBundle
= bundlePtr
? *bundlePtr
: NULL
;
190 CFURLRef url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, CFSTR("/System/Library/CoreServices/SystemVersion.bundle"), kCFURLPOSIXPathStyle
, false);
192 locBundle
= CFBundleCreate(kCFAllocatorSystemDefault
, url
);
197 localized
= CFBundleCopyLocalizedString(locBundle
, nonLocalized
, nonLocalized
, CFSTR("SystemVersion"));
198 if (bundlePtr
) *bundlePtr
= locBundle
; else CFRelease(locBundle
);
200 return localized
? localized
: (CFStringRef
)CFRetain(nonLocalized
);
204 static CFDictionaryRef
_CFCopyVersionDictionary(CFStringRef path
) {
205 CFPropertyListRef plist
= NULL
;
207 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
211 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, path
, kCFURLPOSIXPathStyle
, false);
212 #pragma GCC diagnostic push
213 #pragma GCC diagnostic ignored "-Wdeprecated"
214 if (url
&& CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault
, url
, &data
, NULL
, NULL
, NULL
)) {
215 #pragma GCC diagnostic pop
216 plist
= CFPropertyListCreateWithData(kCFAllocatorSystemDefault
, data
, kCFPropertyListMutableContainers
, NULL
, NULL
);
219 if (url
) CFRelease(url
);
222 #if DEPLOYMENT_TARGET_EMBEDDED_MINI
223 CFStringRef fullVersion
, vers
, versExtra
, build
;
224 CFStringRef versionString
= CFRetain(_kCFSystemVersionProductVersionStringKey
);
225 CFStringRef buildString
= CFRetain(_kCFSystemVersionBuildStringKey
);
226 CFStringRef fullVersionString
= CFRetain(CFSTR("FullVersionString"));
228 CFBundleRef locBundle
= NULL
;
229 CFStringRef fullVersion
, vers
, versExtra
, build
;
230 CFStringRef versionString
= _CFCopyLocalizedVersionKey(&locBundle
, _kCFSystemVersionProductVersionStringKey
);
231 CFStringRef buildString
= _CFCopyLocalizedVersionKey(&locBundle
, _kCFSystemVersionBuildStringKey
);
232 CFStringRef fullVersionString
= _CFCopyLocalizedVersionKey(&locBundle
, CFSTR("FullVersionString"));
233 if (locBundle
) CFRelease(locBundle
);
236 // Now build the full version string
237 if (CFEqual(fullVersionString
, CFSTR("FullVersionString"))) {
238 CFRelease(fullVersionString
);
239 fullVersionString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@ %%@ (%@ %%@)"), versionString
, buildString
);
241 vers
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionProductVersionKey
);
242 versExtra
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionProductVersionExtraKey
);
243 if (vers
&& versExtra
) vers
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@ %@"), vers
, versExtra
);
244 build
= (CFStringRef
)CFDictionaryGetValue((CFDictionaryRef
)plist
, _kCFSystemVersionBuildVersionKey
);
245 fullVersion
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, fullVersionString
, (vers
? vers
: CFSTR("?")), build
? build
: CFSTR("?"));
246 if (vers
&& versExtra
) CFRelease(vers
);
248 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductVersionStringKey
, versionString
);
249 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionBuildStringKey
, buildString
);
250 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, CFSTR("FullVersionString"), fullVersion
);
251 CFRelease(versionString
);
252 CFRelease(buildString
);
253 CFRelease(fullVersionString
);
254 CFRelease(fullVersion
);
256 #elif DEPLOYMENT_TARGET_WINDOWS
257 OSVERSIONINFOEX osvi
;
258 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOEX
));
259 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
260 BOOL result
= GetVersionEx((OSVERSIONINFO
*)&osvi
);
261 if (!result
) return NULL
;
263 plist
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 10, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
266 CFStringRef versionString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%ld.%ld(%ld,%ld)"), osvi
.dwMajorVersion
, osvi
.dwMinorVersion
, osvi
.wServicePackMajor
, osvi
.wServicePackMinor
);
269 CFStringRef buildString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%ld"), osvi
.dwBuildNumber
);
271 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductVersionKey
, versionString
);
272 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionBuildVersionKey
, buildString
);
273 CFDictionarySetValue((CFMutableDictionaryRef
)plist
, _kCFSystemVersionProductNameKey
, CFSTR("Windows")); // hard coded for now
275 CFRelease(versionString
);
276 CFRelease(buildString
);
278 return (CFDictionaryRef
)plist
;
281 CFStringRef
CFCopySystemVersionString(void) {
282 CFStringRef versionString
;
283 CFDictionaryRef dict
= _CFCopyServerVersionDictionary();
284 if (!dict
) dict
= _CFCopySystemVersionDictionary();
285 if (!dict
) return NULL
;
286 versionString
= (CFStringRef
)CFDictionaryGetValue(dict
, CFSTR("FullVersionString"));
287 if (versionString
) CFRetain(versionString
);
289 return versionString
;
292 // Obsolete: These two functions cache the dictionaries to avoid calling _CFCopyVersionDictionary() more than once per dict desired
293 // In fact, they do not cache any more, because the file can change after
294 // apps are running in some situations, and apps need the new info.
295 // Proper caching and testing to see if the file has changed, without race
296 // conditions, would require semi-convoluted use of fstat().
298 static CFStringRef
copySystemVersionPath(CFStringRef suffix
) {
299 #if TARGET_IPHONE_SIMULATOR
300 const char *simulatorRoot
= getenv("IPHONE_SIMULATOR_ROOT");
301 if (!simulatorRoot
) simulatorRoot
= getenv("CFFIXED_USER_HOME");
302 if (!simulatorRoot
) simulatorRoot
= "/";
303 return CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%s%@"), simulatorRoot
, suffix
);
310 CFDictionaryRef
_CFCopySystemVersionDictionary(void) {
311 CFStringRef path
= copySystemVersionPath(CFSTR("/System/Library/CoreServices/SystemVersion.plist"));
312 CFPropertyListRef plist
= _CFCopyVersionDictionary(path
);
314 return (CFDictionaryRef
)plist
;
317 CFDictionaryRef
_CFCopyServerVersionDictionary(void) {
318 CFStringRef path
= copySystemVersionPath(CFSTR("/System/Library/CoreServices/ServerVersion.plist"));
319 CFPropertyListRef plist
= _CFCopyVersionDictionary(path
);
321 return (CFDictionaryRef
)plist
;
324 CONST_STRING_DECL(_kCFSystemVersionProductNameKey
, "ProductName")
325 CONST_STRING_DECL(_kCFSystemVersionProductCopyrightKey
, "ProductCopyright")
326 CONST_STRING_DECL(_kCFSystemVersionProductVersionKey
, "ProductVersion")
327 CONST_STRING_DECL(_kCFSystemVersionProductVersionExtraKey
, "ProductVersionExtra")
328 CONST_STRING_DECL(_kCFSystemVersionProductUserVisibleVersionKey
, "ProductUserVisibleVersion")
329 CONST_STRING_DECL(_kCFSystemVersionBuildVersionKey
, "ProductBuildVersion")
330 CONST_STRING_DECL(_kCFSystemVersionProductVersionStringKey
, "Version")
331 CONST_STRING_DECL(_kCFSystemVersionBuildStringKey
, "Build")
334 CF_EXPORT Boolean
_CFExecutableLinkedOnOrAfter(CFSystemVersion version
) {
341 #if DEPLOYMENT_TARGET_MACOSX
342 CF_PRIVATE
void *__CFLookupCarbonCoreFunction(const char *name
) {
343 static void *image
= NULL
;
345 image
= dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", RTLD_LAZY
| RTLD_LOCAL
);
349 dyfunc
= dlsym(image
, name
);
355 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
356 CF_PRIVATE
void *__CFLookupCoreServicesInternalFunction(const char *name
) {
357 static void *image
= NULL
;
359 image
= dlopen("/System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal", RTLD_LAZY
| RTLD_LOCAL
);
363 dyfunc
= dlsym(image
, name
);
368 CF_PRIVATE
void *__CFLookupCFNetworkFunction(const char *name
) {
369 static void *image
= NULL
;
371 const char *path
= NULL
;
372 if (!__CFProcessIsRestricted()) {
373 path
= __CFgetenv("CFNETWORK_LIBRARY_PATH");
376 path
= "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
378 image
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
382 dyfunc
= dlsym(image
, name
);
388 CF_PRIVATE CFIndex
__CFActiveProcessorCount() {
390 #if DEPLOYMENT_TARGET_WINDOWS
392 GetSystemInfo(&sysInfo
);
393 DWORD_PTR activeProcessorMask
= sysInfo
.dwActiveProcessorMask
;
394 // assumes sizeof(DWORD_PTR) is 64 bits or less
395 uint64_t v
= activeProcessorMask
;
396 v
= v
- ((v
>> 1) & 0x5555555555555555ULL
);
397 v
= (v
& 0x3333333333333333ULL
) + ((v
>> 2) & 0x3333333333333333ULL
);
398 v
= (v
+ (v
>> 4)) & 0xf0f0f0f0f0f0f0fULL
;
399 pcnt
= (v
* 0x0101010101010101ULL
) >> ((sizeof(v
) - 1) * 8);
400 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
401 int32_t mib
[] = {CTL_HW
, HW_AVAILCPU
};
402 size_t len
= sizeof(pcnt
);
403 int32_t result
= sysctl(mib
, sizeof(mib
) / sizeof(int32_t), &pcnt
, &len
, NULL
, 0);
414 CF_PRIVATE
void __CFGetUGIDs(uid_t
*euid
, gid_t
*egid
) {
415 #if 1 && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
418 if (0 == pthread_getugid_np(&uid
, &gid
)) {
419 if (euid
) *euid
= uid
;
420 if (egid
) *egid
= gid
;
424 if (euid
) *euid
= geteuid();
425 if (egid
) *egid
= getegid();
429 const char *_CFPrintForDebugger(const void *obj
) {
430 static char *result
= NULL
;
434 free(result
); // Let go of result from previous call.
437 if (CFGetTypeID(obj
) == CFStringGetTypeID()) {
438 // Makes Ali marginally happier
439 str
= __CFCopyFormattingDescription(obj
, NULL
);
440 if (!str
) str
= CFCopyDescription(obj
);
442 str
= CFCopyDescription(obj
);
445 str
= (CFStringRef
)CFRetain(CFSTR("(null)"));
449 CFStringGetBytes(str
, CFRangeMake(0, CFStringGetLength(str
)), kCFStringEncodingUTF8
, 0, FALSE
, NULL
, 0, &cnt
);
451 result
= (char *) malloc(cnt
+ 2); // 1 for '\0', 1 for an optional '\n'
453 CFStringGetBytes(str
, CFRangeMake(0, CFStringGetLength(str
)), kCFStringEncodingUTF8
, 0, FALSE
, (UInt8
*) result
, cnt
, &cnt
);
457 if (str
) CFRelease(str
);
461 static void _CFShowToFile(FILE *file
, Boolean flush
, const void *obj
) {
464 CFStringInlineBuffer buffer
;
468 if (CFGetTypeID(obj
) == CFStringGetTypeID()) {
469 // Makes Ali marginally happier
470 str
= __CFCopyFormattingDescription(obj
, NULL
);
471 if (!str
) str
= CFCopyDescription(obj
);
473 str
= CFCopyDescription(obj
);
476 str
= (CFStringRef
)CFRetain(CFSTR("(null)"));
478 cnt
= CFStringGetLength(str
);
480 #if DEPLOYMENT_TARGET_WINDOWS
481 UniChar
*ptr
= (UniChar
*)CFStringGetCharactersPtr(str
);
482 BOOL freePtr
= false;
484 CFIndex strLen
= CFStringGetLength(str
);
485 // +2, 1 for newline, 1 for null
486 CFIndex bufSize
= sizeof(UniChar
*) * (CFStringGetMaximumSizeForEncoding(strLen
, kCFStringEncodingUnicode
) + 2);
487 CFIndex bytesUsed
= 0;
488 ptr
= (UniChar
*)malloc(bufSize
);
489 CFStringGetCharacters(str
, CFRangeMake(0, strLen
), ptr
);
494 OutputDebugStringW((wchar_t *)ptr
);
495 if (freePtr
) free(ptr
);
497 CFStringInitInlineBuffer(str
, &buffer
, CFRangeMake(0, cnt
));
498 for (idx
= 0; idx
< cnt
; idx
++) {
499 UniChar ch
= __CFStringGetCharacterFromInlineBufferQuick(&buffer
, idx
);
501 fprintf_l(file
, NULL
, "%c", ch
);
502 lastNL
= (ch
== '\n');
504 fprintf_l(file
, NULL
, "\\u%04x", ch
);
508 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
509 fprintf_l(file
, NULL
, "\n");
511 fprintf(file
, NULL
, "\n");
513 if (flush
) fflush(file
);
517 if (str
) CFRelease(str
);
520 void CFShow(const void *obj
) {
521 _CFShowToFile(stderr
, true, obj
);
525 // message must be a UTF8-encoded, null-terminated, byte buffer with at least length bytes
526 typedef void (*CFLogFunc
)(int32_t lev
, const char *message
, size_t length
, char withBanner
);
528 static Boolean
also_do_stderr() {
529 #if DEPLOYMENT_TARGET_EMBEDDED_MINI
530 // just log to stderr, other logging facilities are out
532 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
533 if (!issetugid() && __CFgetenv("CFLOG_FORCE_STDERR")) {
537 int ret
= fstat(STDERR_FILENO
, &sb
);
538 if (ret
< 0) return false;
539 mode_t m
= sb
.st_mode
& S_IFMT
;
540 if (S_IFREG
== m
|| S_IFSOCK
== m
) return true;
541 if (!(S_IFIFO
== m
|| S_IFCHR
== m
)) return false; // disallow any whacky stuff
542 #if 0 // launchd no longer repeats everything it hears
543 // if it could be a pipe back to launchd, fail
545 // assumes val is not written to on error
546 vproc_swap_integer(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
547 if (val
) return false;
553 extern char *__CFBundleMainID
;
555 static void __CFLogCString(int32_t lev
, const char *message
, size_t length
, char withBanner
) {
562 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
563 // 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.
566 CFAbsoluteTime at
= CFAbsoluteTimeGetCurrent();
567 time_t tv
= floor(at
+ kCFAbsoluteTimeIntervalSince1970
);
569 localtime_r(&tv
, &mine
);
570 int32_t year
= mine
.tm_year
+ 1900;
571 int32_t month
= mine
.tm_mon
+ 1;
572 int32_t day
= mine
.tm_mday
;
573 int32_t hour
= mine
.tm_hour
;
574 int32_t minute
= mine
.tm_min
;
575 int32_t second
= mine
.tm_sec
;
576 int32_t ms
= (int32_t)floor(1000.0 * modf(at
, &dummy
));
577 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
579 if (0 != pthread_threadid_np(NULL
, &tid
)) tid
= pthread_mach_thread_np(pthread_self());
580 asprintf(&banner
, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%llu] ", year
, month
, day
, hour
, minute
, second
, ms
, *_CFGetProgname(), getpid(), tid
);
581 asprintf(&thread
, "%x", pthread_mach_thread_np(pthread_self()));
582 #elif DEPLOYMENT_TARGET_WINDOWS
583 bannerLen
= asprintf(&banner
, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year
, month
, day
, hour
, minute
, second
, ms
, *_CFGetProgname(), getpid(), GetCurrentThreadId());
584 asprintf(&thread
, "%x", GetCurrentThreadId());
586 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());
587 asprintf(&thread
, "%lx", pthread_self());
589 asprintf(&time
, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year
, month
, day
, hour
, minute
, second
, ms
);
592 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
594 __CFGetUGIDs(&euid
, NULL
);
595 asprintf(&uid
, "%d", euid
);
596 aslclient asl
= asl_open(NULL
, __CFBundleMainID
[0] ? __CFBundleMainID
: "com.apple.console", ASL_OPT_NO_DELAY
);
597 aslmsg msg
= asl_new(ASL_TYPE_MSG
);
598 asl_set(msg
, "CFLog Local Time", time
); // not to be documented, not public API
599 asl_set(msg
, "CFLog Thread", thread
); // not to be documented, not public API
600 asl_set(msg
, "ReadUID", uid
);
601 static const char *levstr
[] = {"0", "1", "2", "3", "4", "5", "6", "7"};
602 asl_set(msg
, ASL_KEY_LEVEL
, levstr
[lev
]);
603 asl_set(msg
, ASL_KEY_MSG
, message
);
608 #endif // DEPLOYMENT_TARGET
610 if (also_do_stderr()) {
611 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
613 v
[0].iov_base
= banner
;
614 v
[0].iov_len
= banner
? strlen(banner
) : 0;
615 v
[1].iov_base
= (char *)message
;
616 v
[1].iov_len
= length
;
617 v
[2].iov_base
= "\n";
618 v
[2].iov_len
= (message
[length
- 1] != '\n') ? 1 : 0;
619 int nv
= (v
[0].iov_base
? 1 : 0) + 1 + (v
[2].iov_len
? 1 : 0);
620 static CFLock_t lock
= CFLockInit
;
622 writev(STDERR_FILENO
, v
[0].iov_base
? v
: v
+ 1, nv
);
624 #elif DEPLOYMENT_TARGET_WINDOWS
625 size_t bufLen
= bannerLen
+ length
+ 1;
626 char *buf
= (char *)malloc(sizeof(char) * bufLen
);
628 // Copy the banner into the debug string
629 memmove_s(buf
, bufLen
, banner
, bannerLen
);
631 // Copy the message into the debug string
632 strcpy_s(buf
+ bannerLen
, bufLen
- bannerLen
, message
);
634 strcpy_s(buf
, bufLen
, message
);
636 buf
[bufLen
- 1] = '\0';
637 fprintf_s(stderr
, "%s\n", buf
);
638 // This Win32 API call only prints when a debugger is active
639 // OutputDebugStringA(buf);
642 size_t bufLen
= bannerLen
+ length
+ 1;
643 char *buf
= (char *)malloc(sizeof(char) * bufLen
);
645 // Copy the banner into the debug string
646 memmove(buf
, banner
, bannerLen
);
648 // Copy the message into the debug string
649 strncpy(buf
+ bannerLen
, message
, bufLen
- bannerLen
);
651 strncpy(buf
, message
, bufLen
);
653 buf
[bufLen
- 1] = '\0';
654 fprintf(stderr
, "%s\n", buf
);
659 if (thread
) free(thread
);
660 if (time
) free(time
);
661 if (banner
) free(banner
);
665 CF_EXPORT
void _CFLogvEx2(CFLogFunc logit
, CFStringRef (*copyDescFunc
)(void *, const void *), CFStringRef (*contextDescFunc
)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions
, int32_t lev
, CFStringRef format
, va_list args
) {
666 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
667 uintptr_t val
= (uintptr_t)_CFGetTSD(__CFTSDKeyIsInCFLog
);
668 if (3 < val
) return; // allow up to 4 nested invocations
669 _CFSetTSD(__CFTSDKeyIsInCFLog
, (void *)(val
+ 1), NULL
);
671 CFStringRef str
= format
? _CFStringCreateWithFormatAndArgumentsAux2(kCFAllocatorSystemDefault
, copyDescFunc
, contextDescFunc
, formatOptions
, (CFStringRef
)format
, args
) : 0;
672 CFIndex blen
= str
? CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8
) + 1 : 0;
673 char *buf
= str
? (char *)malloc(blen
) : 0;
675 Boolean converted
= CFStringGetCString(str
, buf
, blen
, kCFStringEncodingUTF8
);
676 size_t len
= strlen(buf
);
677 // silently ignore 0-length or really large messages, and levels outside the valid range
678 if (converted
&& !(len
<= 0 || (1 << 24) < len
) && !(lev
< ASL_LEVEL_EMERG
|| ASL_LEVEL_DEBUG
< lev
)) {
679 (logit
? logit
: __CFLogCString
)(lev
, buf
, len
, 1);
683 if (str
) CFRelease(str
);
684 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
685 _CFSetTSD(__CFTSDKeyIsInCFLog
, (void *)val
, NULL
);
689 CF_EXPORT
void _CFLogvEx(CFLogFunc logit
, CFStringRef (*copyDescFunc
)(void *, const void *), CFDictionaryRef formatOptions
, int32_t lev
, CFStringRef format
, va_list args
) {
690 _CFLogvEx2(logit
, copyDescFunc
, NULL
, formatOptions
, lev
, format
, args
);
693 // 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
694 CF_PRIVATE
void _CFLogSimple(int32_t lev
, char *format
, ...) {
696 va_start(args
, format
);
697 char formattedMessage
[1024];
698 int length
= vsnprintf(formattedMessage
, 1024, format
, args
);
700 __CFLogCString(lev
, formattedMessage
, length
, 0);
705 void CFLog(int32_t lev
, CFStringRef format
, ...) {
707 va_start(args
, format
);
708 _CFLogvEx2(NULL
, NULL
, NULL
, NULL
, lev
, format
, args
);
714 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
716 kern_return_t
_CFDiscorporateMemoryAllocate(CFDiscorporateMemory
*hm
, size_t size
, bool purgeable
) {
717 kern_return_t ret
= KERN_SUCCESS
;
718 size
= round_page(size
);
719 if (0 == size
) size
= vm_page_size
;
720 memset(hm
, 0, sizeof(CFDiscorporateMemory
));
721 void *addr
= mmap(0, size
, PROT_READ
| PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, VM_MAKE_TAG(0) | (purgeable
? VM_FLAGS_PURGABLE
: 0), 0);
722 if ((uintptr_t)addr
== -1) {
725 if (KERN_SUCCESS
== ret
) {
726 hm
->address
= (mach_vm_address_t
)(uintptr_t)addr
;
727 hm
->size
= (mach_vm_size_t
)size
;
728 hm
->port
= MACH_PORT_NULL
;
729 hm
->corporeal
= true;
730 hm
->purgeable
= purgeable
;
732 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
);
733 if (KERN_SUCCESS
== ret
) hm
->corporeal
= true;
737 kern_return_t
_CFDiscorporateMemoryDeallocate(CFDiscorporateMemory
*hm
) {
738 kern_return_t ret1
= KERN_SUCCESS
, ret2
= KERN_SUCCESS
;
739 if (hm
->corporeal
) ret1
= mach_vm_deallocate(mach_task_self(), hm
->address
, hm
->size
);
740 hm
->address
= MACH_VM_MIN_ADDRESS
;
741 hm
->corporeal
= false;
742 ret2
= mach_port_deallocate(mach_task_self(), hm
->port
);
743 hm
->port
= MACH_PORT_NULL
;
744 return ret1
!= KERN_SUCCESS
? ret1
: ret2
;
747 kern_return_t
_CFDiscorporateMemoryDematerialize(CFDiscorporateMemory
*hm
) {
748 kern_return_t ret
= KERN_SUCCESS
;
749 if (!hm
->corporeal
) ret
= KERN_INVALID_MEMORY_CONTROL
;
750 int state
= VM_PURGABLE_VOLATILE
;
751 if (KERN_SUCCESS
== ret
) vm_purgable_control(mach_task_self(), (vm_address_t
)hm
->address
, VM_PURGABLE_SET_STATE
, &state
);
752 if (KERN_SUCCESS
== ret
) ret
= mach_vm_deallocate(mach_task_self(), hm
->address
, hm
->size
);
753 if (KERN_SUCCESS
== ret
) hm
->address
= MACH_VM_MIN_ADDRESS
;
754 if (KERN_SUCCESS
== ret
) hm
->corporeal
= false;
758 kern_return_t
_CFDiscorporateMemoryMaterialize(CFDiscorporateMemory
*hm
) {
759 kern_return_t ret
= KERN_SUCCESS
;
760 if (hm
->corporeal
) ret
= KERN_INVALID_MEMORY_CONTROL
;
761 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
);
762 if (KERN_SUCCESS
== ret
) hm
->corporeal
= true;
763 int state
= VM_PURGABLE_NONVOLATILE
;
764 if (KERN_SUCCESS
== ret
) ret
= vm_purgable_control(mach_task_self(), (vm_address_t
)hm
->address
, VM_PURGABLE_SET_STATE
, &state
);
765 if (KERN_SUCCESS
== ret
) if (VM_PURGABLE_EMPTY
== state
) ret
= KERN_PROTECTION_FAILURE
; // same as VM_PURGABLE_EMPTY
771 #if DEPLOYMENT_TARGET_MACOSX
773 #define SUDDEN_TERMINATION_ENABLE_VPROC 1
775 #if SUDDEN_TERMINATION_ENABLE_VPROC
777 static OSSpinLock __CFProcessKillingLock
= OS_SPINLOCK_INIT
;
778 static CFIndex __CFProcessKillingDisablingCount
= 1;
779 static Boolean __CFProcessKillingWasTurnedOn
= false;
781 void _CFSuddenTerminationDisable(void) {
782 OSSpinLockLock(&__CFProcessKillingLock
);
783 __CFProcessKillingDisablingCount
++;
784 _vproc_transaction_begin();
785 OSSpinLockUnlock(&__CFProcessKillingLock
);
788 void _CFSuddenTerminationEnable(void) {
789 // 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.
790 OSSpinLockLock(&__CFProcessKillingLock
);
791 __CFProcessKillingDisablingCount
--;
792 if (__CFProcessKillingDisablingCount
==0 && !__CFProcessKillingWasTurnedOn
) {
793 _vproc_transactions_enable();
794 __CFProcessKillingWasTurnedOn
= true;
796 // 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.
797 if (__CFProcessKillingDisablingCount
>=0) {
798 _vproc_transaction_end();
800 CFLog(kCFLogLevelError
, CFSTR("-[NSProcessInfo enableSuddenTermination] has been invoked more times than necessary to balance invocations of -[NSProcessInfo disableSuddenTermination]. Ignoring."));
803 OSSpinLockUnlock(&__CFProcessKillingLock
);
806 void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus
) {
807 // 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.
808 OSSpinLockLock(&__CFProcessKillingLock
);
809 // 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.
810 if (__CFProcessKillingWasTurnedOn
) {
811 _vproc_transaction_try_exit(exitStatus
);
813 OSSpinLockUnlock(&__CFProcessKillingLock
);
816 void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus
) {
817 // The user has had their final opportunity to cancel quitting. Exit as soon as the process is clean. Same carefulness as in _CFSuddenTerminationExitIfTerminationEnabled().
818 OSSpinLockLock(&__CFProcessKillingLock
);
819 if (__CFProcessKillingWasTurnedOn
) {
821 OSSpinLockUnlock(&__CFProcessKillingLock
);
824 size_t _CFSuddenTerminationDisablingCount(void) {
825 // 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.
826 return _vproc_transaction_count() + (__CFProcessKillingWasTurnedOn
? 0 : 1);
831 #warning Building with vproc sudden termination API disabled.
833 static OSSpinLockUnlock __CFProcessKillingLock
= OS_SPINLOCK_INIT
;
834 static size_t __CFProcessKillingDisablingCount
= 1;
835 static Boolean __CFProcessExitNextTimeKillingIsEnabled
= false;
836 static int32_t __CFProcessExitStatus
= 0;
837 static int __CFProcessIsKillableNotifyToken
;
838 static Boolean __CFProcessIsKillableNotifyTokenIsFigured
= false;
840 CF_PRIVATE
void _CFSetSuddenTerminationEnabled(Boolean isEnabled
) {
841 if (!__CFProcessIsKillableNotifyTokenIsFigured
) {
842 char *notificationName
= NULL
;
843 asprintf(¬ificationName
, "com.apple.isKillable.%i", getpid());
844 uint32_t notifyResult
= notify_register_check(notificationName
, &__CFProcessIsKillableNotifyToken
);
845 if (notifyResult
!= NOTIFY_STATUS_OK
) {
846 CFLog(kCFLogLevelError
, CFSTR("%s: notify_register_check() returned %i."), __PRETTY_FUNCTION__
, notifyResult
);
848 free(notificationName
);
849 __CFProcessIsKillableNotifyTokenIsFigured
= true;
851 uint32_t notifyResult
= notify_set_state(__CFProcessIsKillableNotifyToken
, isEnabled
);
852 if (notifyResult
!= NOTIFY_STATUS_OK
) {
853 CFLog(kCFLogLevelError
, CFSTR("%s: notify_set_state() returned %i"), __PRETTY_FUNCTION__
, notifyResult
);
857 void _CFSuddenTerminationDisable(void) {
858 OSSpinLockLock(&__CFProcessKillingLock
);
859 if (__CFProcessKillingDisablingCount
== 0) {
860 _CFSetSuddenTerminationEnabled(false);
862 __CFProcessKillingDisablingCount
++;
863 OSSpinLockUnlock(&__CFProcessKillingLock
);
866 void _CFSuddenTerminationEnable(void) {
867 OSSpinLockLock(&__CFProcessKillingLock
);
868 __CFProcessKillingDisablingCount
--;
869 if (__CFProcessKillingDisablingCount
== 0) {
870 if (__CFProcessExitNextTimeKillingIsEnabled
) {
871 _exit(__CFProcessExitStatus
);
873 _CFSetSuddenTerminationEnabled(true);
876 OSSpinLockUnlock(&__CFProcessKillingLock
);
879 void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus
) {
880 OSSpinLockLock(&__CFProcessKillingLock
);
881 if (__CFProcessKillingDisablingCount
== 0) {
884 OSSpinLockUnlock(&__CFProcessKillingLock
);
887 void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus
) {
888 OSSpinLockLock(&__CFProcessKillingLock
);
889 if (__CFProcessKillingDisablingCount
== 0) {
892 __CFProcessExitNextTimeKillingIsEnabled
= YES
;
893 __CFProcessExitStatus
= exitStatus
;
895 OSSpinLockUnlock(&__CFProcessKillingLock
);
898 size_t _CFSuddenTerminationDisablingCount(void) {
899 return __CFProcessKillingDisablingCount
;
907 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
909 typedef void (^ThrottleTypeA
)(void); // allows calls per nanoseconds
910 typedef void (^ThrottleTypeB
)(uint64_t amt
); // allows amount per nanoseconds
912 CF_PRIVATE ThrottleTypeA
__CFCreateThrottleTypeA(uint16_t calls
, uint64_t nanoseconds
) {
913 struct mach_timebase_info info
;
914 mach_timebase_info(&info
);
915 uint64_t period
= nanoseconds
/ info
.numer
* info
.denom
;
917 if (0 == calls
|| 0 == period
) return NULL
;
919 __block OSSpinLock b_lock
= OS_SPINLOCK_INIT
;
920 __block
uint64_t b_values
[calls
];
921 __block
uint64_t *b_oldest
= b_values
;
922 memset(b_values
, 0, sizeof(b_values
));
925 uint64_t curr_time
= mach_absolute_time();
926 OSSpinLockLock(&b_lock
);
927 uint64_t next_time
= *b_oldest
+ period
;
928 *b_oldest
= (curr_time
< next_time
) ? next_time
: curr_time
;
930 if (b_values
+ calls
<= b_oldest
) b_oldest
= b_values
;
931 OSSpinLockUnlock(&b_lock
);
932 if (curr_time
< next_time
) {
933 mach_wait_until(next_time
);
938 CF_PRIVATE ThrottleTypeB
__CFCreateThrottleTypeB(uint64_t amount
, uint64_t nanoseconds
) {
939 struct mach_timebase_info info
;
940 mach_timebase_info(&info
);
941 uint64_t period
= nanoseconds
/ info
.numer
* info
.denom
;
943 if (0 == amount
|| 0 == period
) return NULL
;
945 __block OSSpinLock b_lock
= OS_SPINLOCK_INIT
;
946 __block
uint64_t b_sum
= 0ULL;
947 __block
uint16_t b_num_values
= 8;
948 __block
uint64_t *b_values
= calloc(b_num_values
, 2 * sizeof(uint64_t));
949 __block
uint64_t *b_oldest
= b_values
;
951 return Block_copy(^(uint64_t amt
){
952 OSSpinLockLock(&b_lock
);
954 OSSpinLockUnlock(&b_lock
);
961 #pragma mark File Reading
963 #include <sys/stat.h>
966 #if DEPLOYMENT_TARGET_WINDOWS
972 #define open _NS_open
973 #define stat _NS_stat
975 #define statinfo _stat
977 #define mach_task_self() 0
980 #define statinfo stat
983 static CFErrorRef
_CFErrorWithFilePathCodeDomain(CFStringRef domain
, CFIndex code
, CFStringRef path
) {
984 CFStringRef key
= CFSTR("NSFilePath");
985 CFDictionaryRef userInfo
= CFDictionaryCreate(kCFAllocatorSystemDefault
, (const void **)&key
, (const void **)&path
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
986 CFErrorRef result
= CFErrorCreate(kCFAllocatorSystemDefault
, domain
, code
, userInfo
);
991 // Caller is responsible for freeing memory. munmap() if map == true, else malloc().
992 CF_PRIVATE Boolean
_CFReadMappedFromFile(CFStringRef path
, Boolean map
, Boolean uncached
, void **outBytes
, CFIndex
*outLength
, CFErrorRef
*errorPtr
) {
994 unsigned long length
;
995 char cpath
[CFMaxPathSize
];
996 if (!CFStringGetFileSystemRepresentation(path
, cpath
, CFMaxPathSize
)) {
997 // TODO: real error codes
998 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainCocoa
, -1, path
);
1002 struct statinfo statBuf
;
1005 fd
= open(cpath
, O_RDONLY
|CF_OPENFLGS
, 0666);
1007 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, errno
, path
);
1010 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1011 if (uncached
) (void)fcntl(fd
, F_NOCACHE
, 1); // Non-zero arg turns off caching; we ignore error as uncached is just a hint
1013 if (fstat(fd
, &statBuf
) < 0) {
1014 int32_t savederrno
= errno
;
1016 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1019 if ((statBuf
.st_mode
& S_IFMT
) != S_IFREG
) {
1021 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, EACCES
, path
);
1024 if (statBuf
.st_size
< 0LL) { // too small
1026 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, ENOMEM
, path
);
1031 if (statBuf
.st_size
> (1LL << 31)) { // refuse to do more than 2GB
1033 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, EFBIG
, path
);
1038 if (0LL == statBuf
.st_size
) {
1039 bytes
= malloc(8); // don't return constant string -- it's freed!
1041 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
1043 if((void *)-1 == (bytes
= mmap(0, (size_t)statBuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0))) {
1044 int32_t savederrno
= errno
;
1046 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1049 length
= (unsigned long)statBuf
.st_size
;
1051 bytes
= malloc(statBuf
.st_size
);
1052 if (bytes
== NULL
) {
1054 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, ENOMEM
, path
);
1057 size_t numBytesRemaining
= (size_t)statBuf
.st_size
;
1058 void *readLocation
= bytes
;
1059 while (numBytesRemaining
> 0) {
1060 size_t numBytesRequested
= (numBytesRemaining
< (1LL << 31)) ? numBytesRemaining
: ((1LL << 31) - 1); // This loop is basically a workaround for 4870206
1061 ssize_t numBytesRead
= read(fd
, readLocation
, numBytesRequested
);
1062 if (numBytesRead
<= 0) {
1063 if (numBytesRead
< 0) {
1064 int32_t savederrno
= errno
;
1067 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, savederrno
, path
);
1071 // This is a bizarre case; 0 bytes read. Might indicate end-of-file?
1075 readLocation
+= numBytesRead
;
1076 numBytesRemaining
-= numBytesRead
;
1079 length
= (unsigned long)statBuf
.st_size
- numBytesRemaining
;
1081 #elif DEPLOYMENT_TARGET_WINDOWS
1083 bytes
= malloc(statBuf
.st_size
);
1085 if (!ReadFile((HANDLE
)_get_osfhandle(fd
), bytes
, statBuf
.st_size
, &numBytesRead
, NULL
)) {
1086 DWORD lastError
= GetLastError();
1087 if (errorPtr
) *errorPtr
= _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX
, lastError
, path
);
1094 length
= numBytesRead
;
1099 *outLength
= length
;