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 20 using BPrivate::Libroot::GetCurrentLocaleBackend; 21 using BPrivate::Libroot::LocaleBackend; 22 23 24 static char sStandardTZName[64] = { "GMT" }; 25 static char sDaylightSavingTZName[64] = { "GMT" }; 26 27 28 char* tzname[2] = { 29 sStandardTZName, 30 sDaylightSavingTZName 31 }; 32 long timezone = 0; 33 int daylight = 0; 34 35 36 // These three functions are used as a fallback when the locale backend could not 37 // be loaded. They are implemented in localtime_fading_out.c. 38 extern "C" struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp); 39 extern "C" time_t __mktime_fallback(struct tm* tmp); 40 extern "C" time_t __timegm_fallback(struct tm* tmp); 41 42 43 extern "C" void 44 tzset(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 56 extern "C" struct tm* 57 localtime(const time_t* inTime) 58 { 59 static tm tm; 60 61 return localtime_r(inTime, &tm); 62 } 63 64 65 extern "C" struct tm* 66 localtime_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 92 extern "C" struct tm* 93 gmtime(const time_t* inTime) 94 { 95 static tm tm; 96 97 return gmtime_r(inTime, &tm); 98 } 99 100 101 extern "C" struct tm* 102 gmtime_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 128 extern "C" time_t 129 mktime(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 158 extern "C" time_t 159 timegm(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