diff --git a/headers/private/libroot/time/ICUTimeBackend.h b/headers/private/libroot/time/ICUTimeBackend.h new file mode 100644 index 0000000000..92190dd6a9 --- /dev/null +++ b/headers/private/libroot/time/ICUTimeBackend.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _ICU_TIME_BACKEND_H +#define _ICU_TIME_BACKEND_H + + +#include + + +namespace BPrivate { + + +class ICUTimeBackend : public TimeBackend { +public: + ICUTimeBackend(); + virtual ~ICUTimeBackend(); + + virtual const status_t TZSet(); + + virtual void Initialize(TimeDataBridge* dataBridge); + +private: + TimeDataBridge fDataBridge; +}; + + +} // namespace BPrivate + + +#endif // _ICU_TIME_BACKEND_H diff --git a/headers/private/libroot/time/TimeBackend.h b/headers/private/libroot/time/TimeBackend.h new file mode 100644 index 0000000000..e4256a396c --- /dev/null +++ b/headers/private/libroot/time/TimeBackend.h @@ -0,0 +1,43 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _TIME_BACKEND_H +#define _TIME_BACKEND_H + + +#include + + +namespace BPrivate { + + +struct TimeDataBridge { + int* addrOfDaylight; + long* addrOfTimezone; + char** addrOfTZName; + + TimeDataBridge(); +}; + + +class TimeBackend { +public: + TimeBackend(); + virtual ~TimeBackend(); + + virtual const status_t TZSet() = 0; + + virtual void Initialize(TimeDataBridge* dataBridge) = 0; + + static status_t LoadBackend(); +}; + + +extern TimeBackend* gTimeBackend; + + +} // namespace BPrivate + + +#endif // _TIME_BACKEND_H diff --git a/src/system/libroot/add-ons/icu/time/ICUTimeBackend.cpp b/src/system/libroot/add-ons/icu/time/ICUTimeBackend.cpp new file mode 100644 index 0000000000..b3961eb71c --- /dev/null +++ b/src/system/libroot/add-ons/icu/time/ICUTimeBackend.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ + + +#include "ICUTimeBackend.h" + +#include + +#include + +#include + +#include + + +namespace BPrivate { + + +extern "C" TimeBackend* +CreateInstance() +{ + return new(std::nothrow) ICUTimeBackend(); +} + + +ICUTimeBackend::ICUTimeBackend() +{ +} + + +ICUTimeBackend::~ICUTimeBackend() +{ +} + + +void +ICUTimeBackend::Initialize(TimeDataBridge* dataBridge) +{ + fDataBridge = dataBridge; +} + + +void +ICUTimeBackend::TZSet(void) +{ + ErrnoMaintainer errnoMaintainer; + + TimeZone* icuTimeZone; + if (zoneCode == NULL || zoneCode[0] == '\0') + icuTimeZone = TimeZone::createDefault(); + else + icuTimeZone = TimeZone::createTimeZone(zoneCode); + + UnicodeString unicodeString; + icuTimeZone->getID(unicodeString); + BStringByteSink converter(&fCode); + unicodeString.toUTF8(converter); + + unicodeString.remove(); + icuTimeZone->getDisplayName(unicodeString); + converter.SetTo(&fName); + unicodeString.toUTF8(converter); + + int32_t rawOffset; + int32_t dstOffset; + UDate nowMillis = 1000 * (double)time(NULL); + + UErrorCode error = U_ZERO_ERROR; + icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); + if (!U_SUCCESS(error)) { + fOffsetFromGMT = 0; + fInitStatus = B_ERROR; + } else { + fOffsetFromGMT = (rawOffset + dstOffset) / 1000; + // we want seconds, not ms (which ICU gives us) + fInitStatus = B_OK; + } + + delete icuTimeZone; +} + + +} // namespace BPrivate diff --git a/src/system/libroot/posix/time/Jamfile b/src/system/libroot/posix/time/Jamfile index 23d2c5430a..5384ec2b35 100644 --- a/src/system/libroot/posix/time/Jamfile +++ b/src/system/libroot/posix/time/Jamfile @@ -13,7 +13,8 @@ MergeObject posix_time.o : clock.c ctime.c difftime.c - localtime.c + localtime_fading_out.c + localtime.cpp nanosleep.c stime.c strftime.c diff --git a/src/system/libroot/posix/time/TimeBackend.cpp b/src/system/libroot/posix/time/TimeBackend.cpp new file mode 100644 index 0000000000..5736665fac --- /dev/null +++ b/src/system/libroot/posix/time/TimeBackend.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ + + +#include "TimeBackend.h" + +#include +#include + + +namespace BPrivate { + + +TimeBackend* gTimeBackend = NULL; + + +static TimeDataBridge sTimeDataBridge; +static pthread_once_t sBackendInitOnce = PTHREAD_ONCE_INIT; + + +static void +LoadBackend() +{ + void* imageHandle = dlopen("libroot-addon-icu.so", RTLD_LAZY); + if (imageHandle == NULL) + return; + + typedef TimeBackend* (*symbolType)(); + symbolType createInstanceFunc + = (symbolType)dlsym(imageHandle, "CreateInstance"); + if (createInstanceFunc == NULL) + return; + + gTimeBackend = createInstanceFunc(); +} + + +TimeBackend::TimeBackend() +{ +} + + +TimeBackend::~TimeBackend() +{ +} + + +status_t +TimeBackend::LoadBackend() +{ + if (gTimeBackend == NULL) { + pthread_once(&sBackendInitOnce, &BPrivate::LoadBackend); + if (gTimeBackend != NULL) + gTimeBackend->Initialize(&sTimeDataBridge); + } + + return gTimeBackend != NULL ? B_OK : B_ERROR; +} + + +} // namespace BPrivate diff --git a/src/system/libroot/posix/time/TimeDataBridge.cpp b/src/system/libroot/posix/time/TimeDataBridge.cpp new file mode 100644 index 0000000000..938ade1c4e --- /dev/null +++ b/src/system/libroot/posix/time/TimeDataBridge.cpp @@ -0,0 +1,22 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ + + +#include "TimeBackend.h" + + +namespace BPrivate { + + +TimeDataBridge::TimeDataBridge() + : + addrOfDaylight(&daylight), + addrOfTimezone(&timezone), + addrOfTZName(tzname) +{ +} + + +} // namespace BPrivate diff --git a/src/system/libroot/posix/time/localtime.cpp b/src/system/libroot/posix/time/localtime.cpp new file mode 100644 index 0000000000..5392f03433 --- /dev/null +++ b/src/system/libroot/posix/time/localtime.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include + +#include + +#include +#include + + +char* tzname[2] = { "???", "???" }; +long timezone = 0; +int daylight = 0; + + +namespace BPrivate { + + +static time_zone_info tzInfo; + + +extern "C" void +tzset(void) +{ + char path[B_PATH_NAME_LENGTH]; + if (find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false, path, + sizeof(path)) < 0) + return; + strlcat(path, "/", sizeof(path)); + strlcat(path, skPosixTimeZoneInfoFile, sizeof(path)); + + FILE* tzInfoFile = fopen(path, "r"); + if (tzInfoFile == NULL) + return; + + size_t numRead = fread(&tzInfo, sizeof(tzInfo), 1, tzInfoFile); + fclose(tzInfoFile); + + if (numRead != 1) + return; + + tzname[0] = tzInfo.short_std_name; + tzname[1] = tzInfo.short_dst_name; + timezone = tzInfo.offset_from_gmt; + daylight = tzInfo.uses_daylight_saving; +} + + +} // namespace BPrivate diff --git a/src/system/libroot/posix/time/localtime.c b/src/system/libroot/posix/time/localtime_fading_out.c similarity index 99% rename from src/system/libroot/posix/time/localtime.c rename to src/system/libroot/posix/time/localtime_fading_out.c index 41a0cd7662..3ad9106f78 100644 --- a/src/system/libroot/posix/time/localtime.c +++ b/src/system/libroot/posix/time/localtime_fading_out.c @@ -202,10 +202,12 @@ static char lcl_TZname[TZ_STRLEN_MAX + 1]; static int lcl_is_set; static int gmt_is_set; +#if 0 char * tzname[2] = { wildabbr, wildabbr }; +#endif /* ** Section 4.12.3 of X3.159-1989 requires that @@ -217,10 +219,12 @@ char * tzname[2] = { static struct tm tm; +#if 0 #ifdef USG_COMPAT time_t timezone = 0; int daylight = 0; #endif /* defined USG_COMPAT */ +#endif #ifdef ALTZONE time_t altzone = 0; @@ -1164,6 +1168,7 @@ tzsetwall P((void)) #include #include +#if 0 void tzset P((void)) { @@ -1212,6 +1217,7 @@ tzset P((void)) (void) gmtload(lclptr); settzname(); } +#endif /* ** The easy way to behave "as if no library function calls" localtime