xref: /haiku/src/system/libroot/posix/time/localtime.cpp (revision 372b901dfeada686207d00bbcce456f748bbda12)
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::gLocaleBackend;
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 (gLocaleBackend == 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 	gLocaleBackend->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 	if (gLocaleBackend != NULL) {
75 		status_t status = gLocaleBackend->Localtime(inTime, tmOut);
76 
77 		if (status != B_OK)
78 			__set_errno(EOVERFLOW);
79 
80 		return tmOut;
81 	}
82 
83 	// without a locale backend, there are no timezones, so we fall back to
84 	// using a basic gmtime_r implementation.
85 	return __gmtime_r_fallback(inTime, tmOut);
86 }
87 
88 
89 extern "C" struct tm*
90 gmtime(const time_t* inTime)
91 {
92 	static tm tm;
93 
94 	return gmtime_r(inTime, &tm);
95 }
96 
97 
98 extern "C" struct tm*
99 gmtime_r(const time_t* inTime, struct tm* tmOut)
100 {
101 	if (inTime == NULL) {
102 		__set_errno(EINVAL);
103 		return NULL;
104 	}
105 
106 	tzset();
107 	if (gLocaleBackend != NULL) {
108 		status_t status = gLocaleBackend->Gmtime(inTime, tmOut);
109 
110 		if (status != B_OK)
111 			__set_errno(EOVERFLOW);
112 
113 		return tmOut;
114 	}
115 
116 	// without a locale backend, we fall back to using a basic gmtime_r
117 	// implementation.
118 	return __gmtime_r_fallback(inTime, tmOut);
119 }
120 
121 
122 extern "C" time_t
123 mktime(struct tm* inTm)
124 {
125 	if (inTm == NULL) {
126 		__set_errno(EINVAL);
127 		return -1;
128 	}
129 
130 	tzset();
131 	if (gLocaleBackend != NULL) {
132 		time_t timeOut;
133 		status_t status = gLocaleBackend->Mktime(inTm, timeOut);
134 
135 		if (status != B_OK) {
136 			__set_errno(EOVERFLOW);
137 			return -1;
138 		}
139 
140 		return timeOut;
141 	}
142 
143 	// without a locale backend, we fall back to using a basic gmtime_r
144 	// implementation.
145 	return __mktime_fallback(inTm);
146 }
147 
148 
149 extern "C" time_t
150 timegm(struct tm* inTm)
151 {
152 	if (inTm == NULL) {
153 		__set_errno(EINVAL);
154 		return -1;
155 	}
156 	tzset();
157 	if (gLocaleBackend != NULL) {
158 		time_t timeOut;
159 		status_t status = gLocaleBackend->Timegm(inTm, timeOut);
160 
161 		if (status != B_OK) {
162 			__set_errno(EOVERFLOW);
163 			return -1;
164 		}
165 
166 		return timeOut;
167 	}
168 
169 	// without a locale backend, we fall back to using a basic timegm
170 	// implementation.
171 	return __timegm_fallback(inTm);
172 }
173