Merge remote-tracking branch 'origin/master' into swift-4.0-branch
diff --git a/CoreFoundation/NumberDate.subproj/CFTimeZone.c b/CoreFoundation/NumberDate.subproj/CFTimeZone.c
index 434203a..427a3b1 100644
--- a/CoreFoundation/NumberDate.subproj/CFTimeZone.c
+++ b/CoreFoundation/NumberDate.subproj/CFTimeZone.c
@@ -33,9 +33,12 @@
#endif
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
#include <tzfile.h>
+#define MACOS_TZDIR1 "/usr/share/zoneinfo/" // 10.12 and earlier
+#define MACOS_TZDIR2 "/var/db/timezone/zoneinfo/" // 10.13 onwards
+
#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
#ifndef TZDIR
-#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
+#define TZDIR "/usr/share/zoneinfo/" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
@@ -56,16 +59,9 @@
#include <time.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-#define TZZONELINK TZDEFAULT
-#define TZZONEINFO TZDIR "/"
-#elif DEPLOYMENT_TARGET_WINDOWS
static CFStringRef __tzZoneInfo = NULL;
static char *__tzDir = NULL;
static void __InitTZStrings(void);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
@@ -147,13 +143,9 @@
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
static CFMutableArrayRef __CFCopyRecursiveDirectoryList() {
CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-#if DEPLOYMENT_TARGET_WINDOWS
if (!__tzDir) __InitTZStrings();
if (!__tzDir) return result;
int fd = open(__tzDir, O_RDONLY);
-#else
- int fd = open(TZDIR "/zone.tab", O_RDONLY);
-#endif
for (; 0 <= fd;) {
uint8_t buffer[4096];
@@ -686,7 +678,7 @@
}
extern CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void);
-void __InitTZStrings(void) {
+static void __InitTZStrings(void) {
static CFLock_t __CFTZDirLock = CFLockInit;
__CFLock(&__CFTZDirLock);
if (!__tzZoneInfo) {
@@ -704,6 +696,50 @@
}
__CFUnlock(&__CFTZDirLock);
}
+
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+static void __InitTZStrings(void) {
+ static dispatch_once_t initOnce = 0;
+
+ dispatch_once(&initOnce, ^{
+ unsigned int major = 0, minor = 0, patch = 0;
+
+ CFDictionaryRef dict = _CFCopySystemVersionDictionary();
+ if (dict) {
+ CFStringRef version = CFDictionaryGetValue(dict, _kCFSystemVersionProductVersionKey);
+ if (version) {
+ const char *cStr = CFStringGetCStringPtr(version, kCFStringEncodingASCII);
+ if (cStr) {
+ if (sscanf(cStr, "%u.%u.%u", &major, &minor, &patch) != 3) {
+ major = 0;
+ minor = 0;
+ patch = 0;
+ }
+ }
+ }
+ CFRelease(dict);
+ }
+
+ // Timezone files moved in High Sierra(10.13)
+ if (major == 10 && minor < 13) {
+ // older versions
+ __tzZoneInfo = CFSTR(MACOS_TZDIR1);
+ __tzDir = MACOS_TZDIR1 "zone.tab";
+ } else {
+ __tzZoneInfo = CFSTR(MACOS_TZDIR2);
+ __tzDir = MACOS_TZDIR2 "zone.tab";
+ }
+ });
+}
+
+#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+static void __InitTZStrings(void) {
+ __tzZoneInfo = CFSTR(TZDIR);
+ __tzDir = TZDIR "zone.tab";
+}
+
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
@@ -748,11 +784,16 @@
CFRelease(name);
if (result) return result;
}
- ret = readlink(TZZONELINK, linkbuf, sizeof(linkbuf));
- if (0 < ret) {
+
+ if (!__tzZoneInfo) __InitTZStrings();
+ ret = readlink(TZDEFAULT, linkbuf, sizeof(linkbuf));
+ if (__tzZoneInfo && (0 < ret)) {
linkbuf[ret] = '\0';
- if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
- name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
+ const char *tzZoneInfo = CFStringGetCStringPtr(__tzZoneInfo, kCFStringEncodingASCII);
+ size_t zoneInfoDirLen = CFStringGetLength(__tzZoneInfo);
+ if (strncmp(linkbuf, tzZoneInfo, zoneInfoDirLen) == 0) {
+ name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + zoneInfoDirLen,
+ strlen(linkbuf) - zoneInfoDirLen + 2, kCFStringEncodingUTF8, false);
} else {
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
}
@@ -1133,12 +1174,12 @@
CFIndex length;
Boolean result = false;
-#if DEPLOYMENT_TARGET_WINDOWS
if (!__tzZoneInfo) __InitTZStrings();
if (!__tzZoneInfo) return NULL;
+#if DEPLOYMENT_TARGET_WINDOWS
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
#else
- baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
+ baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
#endif
if (tryAbbrev) {
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1159,15 +1200,9 @@
CFStringRef mapping = CFDictionaryGetValue(dict, name);
if (mapping) {
name = mapping;
-#if DEPLOYMENT_TARGET_WINDOWS
} else if (CFStringHasPrefix(name, __tzZoneInfo)) {
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
-#else
- } else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
- CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
- CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
-#endif
mapping = CFDictionaryGetValue(dict, unprefixed);
if (mapping) {
name = mapping;
@@ -1340,12 +1375,12 @@
void *bytes;
CFIndex length;
-#if DEPLOYMENT_TARGET_WINDOWS
if (!__tzZoneInfo) __InitTZStrings();
if (!__tzZoneInfo) return NULL;
+#if DEPLOYMENT_TARGET_WINDOWS
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
#else
- baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
+ baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
#endif
if (tryAbbrev) {
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1366,15 +1401,9 @@
CFStringRef mapping = CFDictionaryGetValue(dict, name);
if (mapping) {
name = mapping;
-#if DEPLOYMENT_TARGET_WINDOWS
} else if (CFStringHasPrefix(name, __tzZoneInfo)) {
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
-#else
- } else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
- CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
- CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
-#endif
mapping = CFDictionaryGetValue(dict, unprefixed);
if (mapping) {
name = mapping;
@@ -1549,6 +1578,4 @@
return dict;
}
-#undef TZZONEINFO
-#undef TZZONELINK