xref: /haiku/src/system/libroot/posix/time/localtime.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 two 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 
41 
42 extern "C" void
43 tzset(void)
44 {
45 	if (gLocaleBackend == NULL && LocaleBackend::LoadBackend() != B_OK)
46 		return;
47 
48 	char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
49 	_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
50 
51 	gLocaleBackend->TZSet(timeZoneID, getenv("TZ"));
52 }
53 
54 
55 extern "C" struct tm*
56 localtime(const time_t* inTime)
57 {
58 	static tm tm;
59 
60 	return localtime_r(inTime, &tm);
61 }
62 
63 
64 extern "C" struct tm*
65 localtime_r(const time_t* inTime, struct tm* tmOut)
66 {
67 	if (inTime == NULL) {
68 		__set_errno(EINVAL);
69 		return NULL;
70 	}
71 
72 	tzset();
73 	if (gLocaleBackend != NULL) {
74 		status_t status = gLocaleBackend->Localtime(inTime, tmOut);
75 
76 		if (status != B_OK)
77 			__set_errno(EOVERFLOW);
78 
79 		return tmOut;
80 	}
81 
82 	// without a locale backend, there are no timezones, so we fall back to
83 	// using a basic gmtime_r implementation.
84 	return __gmtime_r_fallback(inTime, tmOut);
85 }
86 
87 
88 extern "C" struct tm*
89 gmtime(const time_t* inTime)
90 {
91 	static tm tm;
92 
93 	return gmtime_r(inTime, &tm);
94 }
95 
96 
97 extern "C" struct tm*
98 gmtime_r(const time_t* inTime, struct tm* tmOut)
99 {
100 	if (inTime == NULL) {
101 		__set_errno(EINVAL);
102 		return NULL;
103 	}
104 
105 	tzset();
106 	if (gLocaleBackend != NULL) {
107 		status_t status = gLocaleBackend->Gmtime(inTime, tmOut);
108 
109 		if (status != B_OK)
110 			__set_errno(EOVERFLOW);
111 
112 		return tmOut;
113 	}
114 
115 	// without a locale backend, we fall back to using a basic gmtime_r
116 	// implementation.
117 	return __gmtime_r_fallback(inTime, tmOut);
118 }
119 
120 
121 extern "C" time_t
122 mktime(struct tm* inTm)
123 {
124 	if (inTm == NULL) {
125 		__set_errno(EINVAL);
126 		return -1;
127 	}
128 
129 	tzset();
130 	if (gLocaleBackend != NULL) {
131 		time_t timeOut;
132 		status_t status = gLocaleBackend->Mktime(inTm, timeOut);
133 
134 		if (status != B_OK) {
135 			__set_errno(EOVERFLOW);
136 			return -1;
137 		}
138 
139 		return timeOut;
140 	}
141 
142 	// without a locale backend, we fall back to using a basic gmtime_r
143 	// implementation.
144 	return __mktime_fallback(inTm);
145 }
146