From 9cfd293793416bab3175776cebb529e8fb1f9185 Mon Sep 17 00:00:00 2001 From: wangmm0220 Date: Mon, 2 Dec 2024 10:22:48 +0800 Subject: [PATCH] feat:[TD-32642] add timezone support in windows --- contrib/CMakeLists.txt | 24 +++++---- include/os/osTimezone.h | 9 +++- source/client/src/clientMain.c | 16 +++--- source/os/CMakeLists.txt | 6 ++- source/os/src/osTimezone.c | 87 +++++++----------------------- source/os/src/timezone/localtime.c | 34 ++++++++---- source/os/src/timezone/private.h | 34 +++++++----- source/os/src/timezone/strftime.c | 6 +-- source/util/src/tconfig.c | 10 ++-- 9 files changed, 105 insertions(+), 121 deletions(-) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 6253d258a8..345f23943d 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -106,7 +106,9 @@ cat("${TD_SUPPORT_DIR}/zlib_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) # cJson cat("${TD_SUPPORT_DIR}/cjson_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) -cat("${TD_SUPPORT_DIR}/tz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) +if(NOT ${TD_WINDOWS}) + cat("${TD_SUPPORT_DIR}/tz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) +endif(NOT ${TD_WINDOWS}) # xz # cat("${TD_SUPPORT_DIR}/xz_CMakeLists.txt.in" ${CONTRIB_TMP_FILE}) @@ -653,16 +655,18 @@ if(${TD_LINUX} AND ${BUILD_WITH_S3}) add_subdirectory(azure-cmake EXCLUDE_FROM_ALL) endif() -execute_process( - COMMAND make TZDIR=${TZ_OUTPUT_PATH}/ clean zic posix_only - WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz" -) +if(NOT ${TD_WINDOWS}) + execute_process( + COMMAND make TZDIR=${TZ_OUTPUT_PATH}/ clean zic posix_only + WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz" + ) -set(TZ_SRC_DIR "${TD_SOURCE_DIR}/source/os/src/timezone") -file(MAKE_DIRECTORY ${TZ_SRC_DIR}) -file(COPY ${TD_CONTRIB_DIR}/tz/private.h ${TD_CONTRIB_DIR}/tz/tzdir.h ${TD_CONTRIB_DIR}/tz/tzfile.h - ${TD_CONTRIB_DIR}/tz/localtime.c ${TD_CONTRIB_DIR}/tz/strftime.c - DESTINATION ${TZ_SRC_DIR}) + set(TZ_SRC_DIR "${TD_SOURCE_DIR}/source/os/src/timezone") + file(MAKE_DIRECTORY ${TZ_SRC_DIR}) + file(COPY ${TD_CONTRIB_DIR}/tz/private.h ${TD_CONTRIB_DIR}/tz/tzdir.h ${TD_CONTRIB_DIR}/tz/tzfile.h + ${TD_CONTRIB_DIR}/tz/localtime.c ${TD_CONTRIB_DIR}/tz/strftime.c + DESTINATION ${TZ_SRC_DIR}) +endif(NOT ${TD_WINDOWS}) # ================================================================================================ # Build test # ================================================================================================ diff --git a/include/os/osTimezone.h b/include/os/osTimezone.h index 79dc854fa4..c9cb55207c 100644 --- a/include/os/osTimezone.h +++ b/include/os/osTimezone.h @@ -25,18 +25,23 @@ extern "C" { extern void* pTimezoneNameMap; +#ifdef WINDOWS +typedef struct void *timezone_t; +#else typedef struct state *timezone_t; struct tm *localtime_rz(timezone_t , time_t const *, struct tm *); time_t mktime_z(timezone_t, struct tm *); timezone_t tzalloc(char const *); void tzfree(timezone_t); - void getTimezoneStr(char *tz); + +#endif + + int32_t taosGetLocalTimezoneOffset(); int32_t taosGetSystemTimezone(char *outTimezone); int32_t taosSetGlobalTimezone(const char *tz); int32_t taosFormatTimezoneStr(time_t t, const char* tzStr, timezone_t sp, char *outTimezoneStr); -int32_t taosIsValidateTimezone(const char *tz); #ifdef __cplusplus } #endif diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 14d8394e25..d87f43dd2b 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -93,9 +93,14 @@ static timezone_t setConnnectionTz(const char* val){ tscDebug("set timezone to %s", val); tz = tzalloc(val); if (tz == NULL) { - tscError("%s unknown timezone %s", __func__, val); - terrno = TAOS_SYSTEM_ERROR(errno); - goto END; + tscWarn("%s unknown timezone %s change to UTC", __func__, val); + val = "UTC"; + tz = tzalloc(val); + if (tz == NULL) { + tscError("%s set timezone %s error", __func__, val); + terrno = TAOS_SYSTEM_ERROR(errno); + goto END; + } } int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t)); if (code != 0){ @@ -159,11 +164,6 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) { if (val != NULL){ - if (strlen(val) == 0){ - tscError("%s empty timezone %s", __func__, val); - code = TSDB_CODE_INVALID_PARA; - goto END; - } timezone_t tz = setConnnectionTz(val); if (tz == NULL){ code = terrno; diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index dbcf0f9080..9dbf940c31 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -1,6 +1,8 @@ aux_source_directory(src OS_SRC) -aux_source_directory(src/timezone OS_TZ) -add_library(os STATIC ${OS_SRC} ${OS_TZ}) +if(NOT ${TD_WINDOWS}) + aux_source_directory(src/timezone OS_TZ) + add_library(os STATIC ${OS_SRC} ${OS_TZ}) +endif(NOT ${TD_WINDOWS}) target_include_directories( os PUBLIC "${TD_SOURCE_DIR}/include/os" diff --git a/source/os/src/osTimezone.c b/source/os/src/osTimezone.c index 762391c17a..a5a839ea35 100644 --- a/source/os/src/osTimezone.c +++ b/source/os/src/osTimezone.c @@ -33,7 +33,8 @@ #include #pragma warning(pop) -char *win_tz[139][2] = {{"China Standard Time", "Asia/Shanghai"}, +#define W_TZ_NUM 139 +char *win_tz[W_TZ_NUM][2] = {{"China Standard Time", "Asia/Shanghai"}, {"AUS Central Standard Time", "Australia/Darwin"}, {"AUS Eastern Standard Time", "Australia/Sydney"}, {"Afghanistan Standard Time", "Asia/Kabul"}, @@ -172,7 +173,8 @@ char *win_tz[139][2] = {{"China Standard Time", "Asia/Shanghai"}, {"West Pacific Standard Time", "Pacific/Port_Moresby"}, {"Yakutsk Standard Time", "Asia/Yakutsk"}, {"Yukon Standard Time", "America/Whitehorse"}}; -char *tz_win[554][2] = {{"Asia/Shanghai", "China Standard Time"}, +#define W_TZ_CITY_NUM 554 +char *tz_win[W_TZ_CITY_NUM][2] = {{"Asia/Shanghai", "China Standard Time"}, {"Africa/Abidjan", "Greenwich Standard Time"}, {"Africa/Accra", "Greenwich Standard Time"}, {"Africa/Addis_Ababa", "E. Africa Standard Time"}, @@ -740,38 +742,19 @@ char *tz_win[554][2] = {{"Asia/Shanghai", "China Standard Time"}, #include #endif -void parseTimeStr(char *p, char to[5]) { - for (int i = 0; i < 5; ++i) { - if (strlen(p) > i) { - to[i] = p[i]; - } else { - to[i] = '0'; - } - } - if (strlen(p) == 2) { - to[1] = '0'; - to[2] = p[1]; - } -} - -int32_t taosIsValidateTimezone(const char *tz) { - return true; -} - int32_t taosSetGlobalTimezone(const char *tz) { - if (tz == NULL || tz[0] == 0) { + if (tz == NULL) { terrno = TSDB_CODE_INVALID_PARA; return terrno; } int32_t code = TSDB_CODE_SUCCESS; uDebug("[tz]set timezone to %s", tz) #ifdef WINDOWS - char winStr[TD_LOCALE_LEN * 2]; - memset(winStr, 0, sizeof(winStr)); - for (size_t i = 0; i < 554; i++) { - if (strcmp(tz_win[i][0], buf) == 0) { - char keyPath[256]; - char keyValue[100]; + char winStr[TD_TIMEZONE_LEN * 2] = {0}; + for (size_t i = 0; i < W_TZ_CITY_NUM; i++) { + if (strcmp(tz_win[i][0], tz) == 0) { + char keyPath[256] = {0}; + char keyValue[100] = {0}; DWORD keyValueSize = sizeof(keyValue); snprintf(keyPath, sizeof(keyPath), "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\%s", tz_win[i][1]); RegGetValue(HKEY_LOCAL_MACHINE, keyPath, "Display", RRF_RT_ANY, NULL, (PVOID)&keyValue, &keyValueSize); @@ -779,40 +762,13 @@ int32_t taosSetGlobalTimezone(const char *tz) { keyValue[4] = (keyValue[4] == '+' ? '-' : '+'); keyValue[10] = 0; snprintf(winStr, sizeof(winStr), "TZ=%s:00", &(keyValue[1])); - *tsTimezone = -taosStr2Int32(&keyValue[4], NULL, 10); } break; } } - if (winStr[0] == 0) { - char *p = strchr(inTimezoneStr, '+'); - if (p == NULL) p = strchr(inTimezoneStr, '-'); - if (p != NULL) { - char *pp = strchr(inTimezoneStr, '('); - char *ppp = strchr(inTimezoneStr, ','); - int indexStr; - if (pp == NULL || ppp == NULL) { - indexStr = tsnprintf(winStr, sizeof(winStr), "TZ=UTC"); - } else { - memcpy(winStr, "TZ=", 3); - pp++; - memcpy(&winStr[3], pp, ppp - pp); - indexStr = ppp - pp + 3; - } - char to[5]; - parseTimeStr(p, to); - snprintf(&winStr[indexStr], sizeof(winStr) - indexStr, "%c%c%c:%c%c:00", (to[0] == '+' ? '+' : '-'), to[1], to[2], to[3], to[4]); - *tsTimezone = -taosStr2Int32(p, NULL, 10); - } else { - *tsTimezone = 0; - } - } + _putenv(winStr); _tzset(); - if (outTimezoneStr != inTimezoneStr) { - tstrncpy(outTimezoneStr, inTimezoneStr, TD_TIMEZONE_LEN); - } -// *outDaylight = 0; #else code = setenv("TZ", tz, 1); if (-1 == code) { @@ -821,11 +777,10 @@ int32_t taosSetGlobalTimezone(const char *tz) { } tzset(); +#endif time_t tx1 = taosGetTimestampSec(); return taosFormatTimezoneStr(tx1, tz, NULL, tsTimezoneStr); -#endif - } int32_t taosGetLocalTimezoneOffset() { @@ -869,6 +824,7 @@ int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *out return 0; } +#ifndef WINDOWS void getTimezoneStr(char *tz) { do { int n = readlink("/etc/localtime", tz, TD_TIMEZONE_LEN - 1); @@ -909,21 +865,20 @@ END: } uDebug("[tz] system timezone:%s", tz); } +#endif int32_t taosGetSystemTimezone(char *outTimezoneStr) { #ifdef WINDOWS - char value[100]; - char keyPath[100]; + char value[100] = {0}; + char keyPath[100] = {0}; DWORD bufferSize = sizeof(value); LONG result = RegGetValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", "TimeZoneKeyName", RRF_RT_ANY, NULL, (PVOID)&value, &bufferSize); if (result != ERROR_SUCCESS) { return TAOS_SYSTEM_WINAPI_ERROR(result); } - tstrncpy(outTimezoneStr, "not configured", TD_TIMEZONE_LEN); - *tsTimezone = 0; if (bufferSize > 0) { - for (size_t i = 0; i < 139; i++) { + for (size_t i = 0; i < W_TZ_NUM; i++) { if (strcmp(win_tz[i][0], value) == 0) { tstrncpy(outTimezoneStr, win_tz[i][1], TD_TIMEZONE_LEN); bufferSize = sizeof(value); @@ -932,11 +887,9 @@ int32_t taosGetSystemTimezone(char *outTimezoneStr) { if (result != ERROR_SUCCESS) { return TAOS_SYSTEM_WINAPI_ERROR(result); } - if (bufferSize > 0) { - // value[4] = (value[4] == '+' ? '-' : '+'); - snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (UTC, %c%c%c%c%c)", outTimezoneStr, value[4], value[5], value[6], value[8], - value[9]); - *tsTimezone = taosStr2Int32(&value[4], NULL, 10); + if (bufferSize > 0) { // value like (UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi + snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (UTC, %c%c%c%c%c)", outTimezoneStr, + value[4], value[5], value[6], value[8], value[9]); } break; } diff --git a/source/os/src/timezone/localtime.c b/source/os/src/timezone/localtime.c index e6d79d05d9..492965d9e4 100644 --- a/source/os/src/timezone/localtime.c +++ b/source/os/src/timezone/localtime.c @@ -145,10 +145,31 @@ static char const *utc = etc_utc + sizeof "Etc/" - 1; # define TZDEFRULESTRING ",M3.2.0,M11.1.0" #endif +/* Limit to time zone abbreviation length in proleptic TZ strings. + This is distinct from TZ_MAX_CHARS, which limits TZif file contents. + It defaults to 254, not 255, so that desigidx_type can be an unsigned char. + unsigned char suffices for TZif files, so the only reason to increase + TZNAME_MAXIMUM is to support TZ strings specifying abbreviations + longer than 254 bytes. There is little reason to do that, though, + as strings that long are hardly "abbreviations". */ +#ifndef TZNAME_MAXIMUM +# define TZNAME_MAXIMUM 254 +#endif + +#if TZNAME_MAXIMUM < UCHAR_MAX +typedef unsigned char desigidx_type; +#elif TZNAME_MAXIMUM < INT_MAX +typedef int desigidx_type; +#elif TZNAME_MAXIMUM < PTRDIFF_MAX +typedef ptrdiff_t desigidx_type; +#else +# error "TZNAME_MAXIMUM too large" +#endif + struct ttinfo { /* time type information */ - int_fast32_t tt_utoff; /* UT offset in seconds */ + int_least32_t tt_utoff; /* UT offset in seconds */ + desigidx_type tt_desigidx; /* abbreviation list index */ bool tt_isdst; /* used to set tm_isdst */ - int tt_desigidx; /* abbreviation list index */ bool tt_ttisstd; /* transition is std time */ bool tt_ttisut; /* transition is UT */ }; @@ -167,12 +188,6 @@ static char const UNSPEC[] = "-00"; for ttunspecified to work without crashing. */ enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; -/* Limit to time zone abbreviation length in proleptic TZ strings. - This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ -#ifndef TZNAME_MAXIMUM -# define TZNAME_MAXIMUM 255 -#endif - /* A representation of the contents of a TZif file. Ideally this would have no size limits; the following sizes should suffice for practical use. This struct should not be too large, as instances @@ -273,7 +288,8 @@ long altzone; /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */ static void -init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx) +init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, + desigidx_type desigidx) { s->tt_utoff = utoff; s->tt_isdst = isdst; diff --git a/source/os/src/timezone/private.h b/source/os/src/timezone/private.h index da6dc79010..edc188a264 100644 --- a/source/os/src/timezone/private.h +++ b/source/os/src/timezone/private.h @@ -88,11 +88,11 @@ #if !defined HAVE_GETTEXT && defined __has_include # if __has_include() -# define HAVE_GETTEXT true +# define HAVE_GETTEXT 1 # endif #endif #ifndef HAVE_GETTEXT -# define HAVE_GETTEXT false +# define HAVE_GETTEXT 0 #endif #ifndef HAVE_INCOMPATIBLE_CTIME_R @@ -125,20 +125,20 @@ #if !defined HAVE_SYS_STAT_H && defined __has_include # if !__has_include() -# define HAVE_SYS_STAT_H false +# define HAVE_SYS_STAT_H 0 # endif #endif #ifndef HAVE_SYS_STAT_H -# define HAVE_SYS_STAT_H true +# define HAVE_SYS_STAT_H 1 #endif #if !defined HAVE_UNISTD_H && defined __has_include # if !__has_include() -# define HAVE_UNISTD_H false +# define HAVE_UNISTD_H 0 # endif #endif #ifndef HAVE_UNISTD_H -# define HAVE_UNISTD_H true +# define HAVE_UNISTD_H 1 #endif #ifndef NETBSD_INSPIRED @@ -263,6 +263,10 @@ # endif #endif +#ifndef HAVE_SNPRINTF +# define HAVE_SNPRINTF (!PORT_TO_C89 || 199901 <= __STDC_VERSION__) +#endif + #ifndef HAVE_STRFTIME_L # if _POSIX_VERSION < 200809 # define HAVE_STRFTIME_L 0 @@ -308,7 +312,7 @@ ** stdint.h, even with pre-C99 compilers. */ #if !defined HAVE_STDINT_H && defined __has_include -# define HAVE_STDINT_H true /* C23 __has_include implies C99 stdint.h. */ +# define HAVE_STDINT_H 1 /* C23 __has_include implies C99 stdint.h. */ #endif #ifndef HAVE_STDINT_H # define HAVE_STDINT_H \ @@ -378,11 +382,15 @@ typedef int int_fast32_t; # endif #endif +#ifndef INT_LEAST32_MAX +typedef int_fast32_t int_least32_t; +#endif + #ifndef INTMAX_MAX # ifdef LLONG_MAX typedef long long intmax_t; # ifndef HAVE_STRTOLL -# define HAVE_STRTOLL true +# define HAVE_STRTOLL 1 # endif # if HAVE_STRTOLL # define strtoimax strtoll @@ -462,7 +470,7 @@ typedef unsigned long uintmax_t; hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG. */ #if !defined HAVE_STDCKDINT_H && defined __has_include # if __has_include() -# define HAVE_STDCKDINT_H true +# define HAVE_STDCKDINT_H 1 # endif #endif #ifdef HAVE_STDCKDINT_H @@ -630,9 +638,9 @@ typedef unsigned long uintmax_t; ** typical platforms. */ #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0 -# define TZ_TIME_T 1 +# define TZ_TIME_T true #else -# define TZ_TIME_T 0 +# define TZ_TIME_T false #endif #if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T @@ -749,9 +757,9 @@ void tzset(void); || defined __GLIBC__ || defined __tm_zone /* musl */ \ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \ || (defined __APPLE__ && defined __MACH__)) -# define HAVE_DECL_TIMEGM true +# define HAVE_DECL_TIMEGM 1 # else -# define HAVE_DECL_TIMEGM false +# define HAVE_DECL_TIMEGM 0 # endif #endif #if !HAVE_DECL_TIMEGM && !defined timegm diff --git a/source/os/src/timezone/strftime.c b/source/os/src/timezone/strftime.c index fc0c87d20a..487a5234cb 100644 --- a/source/os/src/timezone/strftime.c +++ b/source/os/src/timezone/strftime.c @@ -79,9 +79,9 @@ !defined __NetBSD_Version__ || __NetBSD_Version__ < 600000000) \ && (/* OpenBSD 5.5 (2014-05-01) and later has 64-bit time_t. */ \ !defined OpenBSD || OpenBSD < 201405))) -# define MKTIME_MIGHT_OVERFLOW true +# define MKTIME_MIGHT_OVERFLOW 1 # else -# define MKTIME_MIGHT_OVERFLOW false +# define MKTIME_MIGHT_OVERFLOW 0 # endif #endif /* Check that MKTIME_MIGHT_OVERFLOW is consistent with time_t's range. */ @@ -95,7 +95,7 @@ static_assert(MKTIME_MIGHT_OVERFLOW #endif #ifndef DEPRECATE_TWO_DIGIT_YEARS -# define DEPRECATE_TWO_DIGIT_YEARS false +# define DEPRECATE_TWO_DIGIT_YEARS 0 #endif struct lc_time_T { diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index 57895d0cca..f12f17853a 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -251,13 +251,9 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType TAOS_RETURN(TSDB_CODE_INVALID_CFG); } - if(!taosIsValidateTimezone(value)){ - uError("invalid timezone:%s", value); - TAOS_RETURN(TSDB_CODE_INVALID_TIMEZONE); - } - if (value == NULL || strlen(value) == 0) { - uError("cfg:%s, type:%s src:%s, value:%s, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype), - cfgStypeStr(stype), value); + if (value == NULL) { + uError("cfg:%s, type:%s src:%s, value is null, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype), + cfgStypeStr(stype)); TAOS_RETURN(TSDB_CODE_INVALID_CFG); } TAOS_CHECK_RETURN(osSetTimezone(value));