1/* 2 * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <errno.h> 8#include <stdlib.h> 9#include <string.h> 10#include <time.h> 11 12#include <syscalls.h> 13 14#include <StorageDefs.h> 15 16#include <errno_private.h> 17#include "LocaleBackend.h" 18 19 20using BPrivate::Libroot::GetCurrentLocaleBackend; 21using BPrivate::Libroot::LocaleBackend; 22 23 24static char sStandardTZName[64] = { "GMT" }; 25static char sDaylightSavingTZName[64] = { "GMT" }; 26 27 28char* tzname[2] = { 29 sStandardTZName, 30 sDaylightSavingTZName 31}; 32long timezone = 0; 33int daylight = 0; 34 35 36// These three functions are used as a fallback when the locale backend could not 37// be loaded, or for the POSIX locale. They are implemented in localtime_fallback.c. 38extern "C" struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp); 39extern "C" time_t __mktime_fallback(struct tm* tmp); 40extern "C" time_t __timegm_fallback(struct tm* tmp); 41 42 43extern "C" void 44tzset(void) 45{ 46 if (GetCurrentLocaleBackend() == NULL && LocaleBackend::LoadBackend() != B_OK) 47 return; 48 49 char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" }; 50 _kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID)); 51 52 GetCurrentLocaleBackend()->TZSet(timeZoneID, getenv("TZ")); 53} 54 55 56extern "C" struct tm* 57localtime(const time_t* inTime) 58{ 59 static tm tm; 60 61 return localtime_r(inTime, &tm); 62} 63 64 65extern "C" struct tm* 66localtime_r(const time_t* inTime, struct tm* tmOut) 67{ 68 if (inTime == NULL) { 69 __set_errno(EINVAL); 70 return NULL; 71 } 72 73 tzset(); 74 75 LocaleBackend* backend = GetCurrentLocaleBackend(); 76 77 if (backend != NULL) { 78 status_t status = backend->Localtime(inTime, tmOut); 79 80 if (status != B_OK) 81 __set_errno(EOVERFLOW); 82 83 return tmOut; 84 } 85 86 // without a locale backend, there are no timezones, so we fall back to 87 // using a basic gmtime_r implementation. 88 return __gmtime_r_fallback(inTime, tmOut); 89} 90 91 92extern "C" struct tm* 93gmtime(const time_t* inTime) 94{ 95 static tm tm; 96 97 return gmtime_r(inTime, &tm); 98} 99 100 101extern "C" struct tm* 102gmtime_r(const time_t* inTime, struct tm* tmOut) 103{ 104 if (inTime == NULL) { 105 __set_errno(EINVAL); 106 return NULL; 107 } 108 109 tzset(); 110 111 LocaleBackend* backend = GetCurrentLocaleBackend(); 112 113 if (backend != NULL) { 114 status_t status = backend->Gmtime(inTime, tmOut); 115 116 if (status != B_OK) 117 __set_errno(EOVERFLOW); 118 119 return tmOut; 120 } 121 122 // without a locale backend, we fall back to using a basic gmtime_r 123 // implementation. 124 return __gmtime_r_fallback(inTime, tmOut); 125} 126 127 128extern "C" time_t 129mktime(struct tm* inTm) 130{ 131 if (inTm == NULL) { 132 __set_errno(EINVAL); 133 return -1; 134 } 135 136 tzset(); 137 138 LocaleBackend* backend = GetCurrentLocaleBackend(); 139 140 if (backend != NULL) { 141 time_t timeOut; 142 status_t status = backend->Mktime(inTm, timeOut); 143 144 if (status != B_OK) { 145 __set_errno(EOVERFLOW); 146 return -1; 147 } 148 149 return timeOut; 150 } 151 152 // without a locale backend, we fall back to using a basic gmtime_r 153 // implementation. 154 return __mktime_fallback(inTm); 155} 156 157 158extern "C" time_t 159timegm(struct tm* inTm) 160{ 161 if (inTm == NULL) { 162 __set_errno(EINVAL); 163 return -1; 164 } 165 tzset(); 166 167 LocaleBackend* backend = GetCurrentLocaleBackend(); 168 169 if (backend != NULL) { 170 time_t timeOut; 171 status_t status = backend->Timegm(inTm, timeOut); 172 173 if (status != B_OK) { 174 __set_errno(EOVERFLOW); 175 return -1; 176 } 177 178 return timeOut; 179 } 180 181 // without a locale backend, we fall back to using a basic timegm 182 // implementation. 183 return __timegm_fallback(inTm); 184} 185