Skip to content

Commit 80acf1c

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 run on 10.12 and 10.13 - Added __InitTZStrings() for both Linux and macOS to work the same way as Windows.
1 parent 79322e9 commit 80acf1c

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+
// older versions
726+
__tzZoneInfo = CFSTR(MACOS_TZDIR1);
727+
__tzDir = MACOS_TZDIR1 "zone.tab";
728+
} else {
729+
__tzZoneInfo = CFSTR(MACOS_TZDIR2);
730+
__tzDir = MACOS_TZDIR2 "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)