Skip to content

Commit 1ae6f34

Browse files
committed
Determine the Timezone directory to use at runtime on macOS.
- The timezone directory changed on macOS 10.13 so get the os version at runtime and set the timezone directory dynamically. This allows the tests to be on 10.12 and 10.13
1 parent ee8221b commit 1ae6f34

File tree

1 file changed

+62
-35
lines changed

1 file changed

+62
-35
lines changed

CoreFoundation/NumberDate.subproj/CFTimeZone.c

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@
3333
#endif
3434
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3535
#include <tzfile.h>
36+
#define MACOS_TZDIR1 "/usr/share/zoneinfo/" // 10.12 and earlier
37+
#define MACOS_TZDIR2 "/var/db/timezone/zoneinfo/" // 10.13 onwards
38+
3639
#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
3740
#ifndef TZDIR
38-
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
41+
#define TZDIR "/usr/share/zoneinfo/" /* Time zone object file directory */
3942
#endif /* !defined TZDIR */
4043

4144
#ifndef TZDEFAULT
@@ -56,16 +59,9 @@ struct tzhead {
5659

5760
#include <time.h>
5861

59-
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
60-
#define TZZONELINK TZDEFAULT
61-
#define TZZONEINFO TZDIR "/"
62-
#elif DEPLOYMENT_TARGET_WINDOWS
6362
static CFStringRef __tzZoneInfo = NULL;
6463
static char *__tzDir = NULL;
6564
static void __InitTZStrings(void);
66-
#else
67-
#error Unknown or unspecified DEPLOYMENT_TARGET
68-
#endif
6965

7066
CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
7167

@@ -147,13 +143,9 @@ static CFMutableArrayRef __CFCopyWindowsTimeZoneList() {
147143
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
148144
static CFMutableArrayRef __CFCopyRecursiveDirectoryList() {
149145
CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
150-
#if DEPLOYMENT_TARGET_WINDOWS
151146
if (!__tzDir) __InitTZStrings();
152147
if (!__tzDir) return result;
153148
int fd = open(__tzDir, O_RDONLY);
154-
#else
155-
int fd = open(TZDIR "/zone.tab", O_RDONLY);
156-
#endif
157149

158150
for (; 0 <= fd;) {
159151
uint8_t buffer[4096];
@@ -686,7 +678,7 @@ CFTimeZoneRef CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator, CFString
686678
}
687679

688680
extern CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void);
689-
void __InitTZStrings(void) {
681+
static void __InitTZStrings(void) {
690682
static CFLock_t __CFTZDirLock = CFLockInit;
691683
__CFLock(&__CFTZDirLock);
692684
if (!__tzZoneInfo) {
@@ -704,6 +696,50 @@ void __InitTZStrings(void) {
704696
}
705697
__CFUnlock(&__CFTZDirLock);
706698
}
699+
700+
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
701+
static void __InitTZStrings(void) {
702+
static dispatch_once_t initOnce = 0;
703+
704+
dispatch_once(&initOnce, ^{
705+
unsigned int major = 0, minor = 0, patch = 0;
706+
707+
CFDictionaryRef dict = _CFCopySystemVersionDictionary();
708+
if (dict) {
709+
CFStringRef version = CFDictionaryGetValue(dict, _kCFSystemVersionProductVersionKey);
710+
if (version) {
711+
const char *cStr = CFStringGetCStringPtr(version, kCFStringEncodingASCII);
712+
if (cStr) {
713+
if (sscanf(cStr, "%u.%u.%u", &major, &minor, &patch) != 3) {
714+
major = 0,
715+
minor = 0,
716+
patch = 0;
717+
}
718+
}
719+
}
720+
CFRelease(dict);
721+
}
722+
723+
// Timezone files moved in High Sierra(10.13)
724+
if (major == 10 && minor >= 13) {
725+
__tzZoneInfo = CFSTR(MACOS_TZDIR2);
726+
__tzDir = MACOS_TZDIR2 "zone.tab";
727+
} else {
728+
// older versions and fallback if major/minor cant be detected
729+
__tzZoneInfo = CFSTR(MACOS_TZDIR1);
730+
__tzDir = MACOS_TZDIR1 "zone.tab";
731+
}
732+
});
733+
}
734+
735+
#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
736+
static void __InitTZStrings(void) {
737+
__tzZoneInfo = CFSTR(TZDIR);
738+
__tzDir = TZDIR "zone.tab";
739+
}
740+
741+
#else
742+
#error Unknown or unspecified DEPLOYMENT_TARGET
707743
#endif
708744

709745
static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
@@ -748,11 +784,16 @@ static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
748784
CFRelease(name);
749785
if (result) return result;
750786
}
751-
ret = readlink(TZZONELINK, linkbuf, sizeof(linkbuf));
752-
if (0 < ret) {
787+
788+
if (!__tzZoneInfo) __InitTZStrings();
789+
ret = readlink(TZDEFAULT, linkbuf, sizeof(linkbuf));
790+
if (__tzZoneInfo && (0 < ret)) {
753791
linkbuf[ret] = '\0';
754-
if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
755-
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
792+
const char *tzZoneInfo = CFStringGetCStringPtr(__tzZoneInfo, kCFStringEncodingASCII);
793+
size_t zoneInfoDirLen = CFStringGetLength(__tzZoneInfo);
794+
if (strncmp(linkbuf, tzZoneInfo, zoneInfoDirLen) == 0) {
795+
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + zoneInfoDirLen,
796+
strlen(linkbuf) - zoneInfoDirLen + 2, kCFStringEncodingUTF8, false);
756797
} else {
757798
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
758799
}
@@ -1133,12 +1174,12 @@ Boolean _CFTimeZoneInit(CFTimeZoneRef timeZone, CFStringRef name, CFDataRef data
11331174
CFIndex length;
11341175
Boolean result = false;
11351176

1136-
#if DEPLOYMENT_TARGET_WINDOWS
11371177
if (!__tzZoneInfo) __InitTZStrings();
11381178
if (!__tzZoneInfo) return NULL;
1179+
#if DEPLOYMENT_TARGET_WINDOWS
11391180
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
11401181
#else
1141-
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
1182+
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
11421183
#endif
11431184
if (tryAbbrev) {
11441185
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1159,15 +1200,9 @@ Boolean _CFTimeZoneInit(CFTimeZoneRef timeZone, CFStringRef name, CFDataRef data
11591200
CFStringRef mapping = CFDictionaryGetValue(dict, name);
11601201
if (mapping) {
11611202
name = mapping;
1162-
#if DEPLOYMENT_TARGET_WINDOWS
11631203
} else if (CFStringHasPrefix(name, __tzZoneInfo)) {
11641204
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
11651205
CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
1166-
#else
1167-
} else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
1168-
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
1169-
CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
1170-
#endif
11711206
mapping = CFDictionaryGetValue(dict, unprefixed);
11721207
if (mapping) {
11731208
name = mapping;
@@ -1340,12 +1375,12 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
13401375
void *bytes;
13411376
CFIndex length;
13421377

1343-
#if DEPLOYMENT_TARGET_WINDOWS
13441378
if (!__tzZoneInfo) __InitTZStrings();
13451379
if (!__tzZoneInfo) return NULL;
1380+
#if DEPLOYMENT_TARGET_WINDOWS
13461381
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
13471382
#else
1348-
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
1383+
baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLPOSIXPathStyle, true);
13491384
#endif
13501385
if (tryAbbrev) {
13511386
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
@@ -1366,15 +1401,9 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
13661401
CFStringRef mapping = CFDictionaryGetValue(dict, name);
13671402
if (mapping) {
13681403
name = mapping;
1369-
#if DEPLOYMENT_TARGET_WINDOWS
13701404
} else if (CFStringHasPrefix(name, __tzZoneInfo)) {
13711405
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
13721406
CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
1373-
#else
1374-
} else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
1375-
CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
1376-
CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
1377-
#endif
13781407
mapping = CFDictionaryGetValue(dict, unprefixed);
13791408
if (mapping) {
13801409
name = mapping;
@@ -1549,6 +1578,4 @@ static CFDictionaryRef __CFTimeZoneCopyCompatibilityDictionary(void) {
15491578
return dict;
15501579
}
15511580

1552-
#undef TZZONEINFO
1553-
#undef TZZONELINK
15541581

0 commit comments

Comments
 (0)