1 /* |
1 /* |
2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
70 static const char *SYS_INIT_FILE = "/etc/default/init"; |
72 static const char *SYS_INIT_FILE = "/etc/default/init"; |
71 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; |
73 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; |
72 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; |
74 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; |
73 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */ |
75 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */ |
74 |
76 |
|
77 static const char popularZones[][4] = {"UTC", "GMT"}; |
|
78 |
75 #if defined(_AIX) |
79 #if defined(_AIX) |
76 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; |
80 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; |
77 #endif |
81 #endif |
78 |
82 |
79 #if defined(__linux__) || defined(MACOSX) || defined(__solaris__) |
83 #if defined(__linux__) || defined(MACOSX) || defined(__solaris__) |
119 */ |
123 */ |
120 static char * |
124 static char * |
121 findZoneinfoFile(char *buf, size_t size, const char *dir) |
125 findZoneinfoFile(char *buf, size_t size, const char *dir) |
122 { |
126 { |
123 DIR *dirp = NULL; |
127 DIR *dirp = NULL; |
124 struct stat64 statbuf; |
|
125 struct dirent *dp = NULL; |
128 struct dirent *dp = NULL; |
126 char *pathname = NULL; |
129 char *pathname = NULL; |
127 int fd = -1; |
|
128 char *dbuf = NULL; |
|
129 char *tz = NULL; |
130 char *tz = NULL; |
130 int res; |
131 int res; |
131 |
132 |
132 dirp = opendir(dir); |
133 dirp = opendir(dir); |
133 if (dirp == NULL) { |
134 if (dirp == NULL) { |
134 return NULL; |
135 return NULL; |
|
136 } |
|
137 |
|
138 if (strcmp(dir, ZONEINFO_DIR) == 0) { |
|
139 /* fast path for 1st iteration */ |
|
140 for (unsigned int i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) { |
|
141 pathname = getPathName(dir, popularZones[i]); |
|
142 if (pathname == NULL) { |
|
143 continue; |
|
144 } |
|
145 tz = isFileIdentical(buf, size, pathname); |
|
146 free((void *) pathname); |
|
147 pathname = NULL; |
|
148 if (tz != NULL) { |
|
149 return tz; |
|
150 } |
|
151 } |
135 } |
152 } |
136 |
153 |
137 while ((dp = readdir(dirp)) != NULL) { |
154 while ((dp = readdir(dirp)) != NULL) { |
138 /* |
155 /* |
139 * Skip '.' and '..' (and possibly other .* files) |
156 * Skip '.' and '..' (and possibly other .* files) |
160 |
177 |
161 pathname = getPathName(dir, dp->d_name); |
178 pathname = getPathName(dir, dp->d_name); |
162 if (pathname == NULL) { |
179 if (pathname == NULL) { |
163 break; |
180 break; |
164 } |
181 } |
165 RESTARTABLE(stat64(pathname, &statbuf), res); |
182 |
166 if (res == -1) { |
183 tz = isFileIdentical(buf, size, pathname); |
167 break; |
|
168 } |
|
169 |
|
170 if (S_ISDIR(statbuf.st_mode)) { |
|
171 tz = findZoneinfoFile(buf, size, pathname); |
|
172 if (tz != NULL) { |
|
173 break; |
|
174 } |
|
175 } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) { |
|
176 dbuf = (char *) malloc(size); |
|
177 if (dbuf == NULL) { |
|
178 break; |
|
179 } |
|
180 RESTARTABLE(open(pathname, O_RDONLY), fd); |
|
181 if (fd == -1) { |
|
182 break; |
|
183 } |
|
184 RESTARTABLE(read(fd, dbuf, size), res); |
|
185 if (res != (ssize_t) size) { |
|
186 break; |
|
187 } |
|
188 if (memcmp(buf, dbuf, size) == 0) { |
|
189 tz = getZoneName(pathname); |
|
190 if (tz != NULL) { |
|
191 tz = strdup(tz); |
|
192 } |
|
193 break; |
|
194 } |
|
195 free((void *) dbuf); |
|
196 dbuf = NULL; |
|
197 (void) close(fd); |
|
198 fd = -1; |
|
199 } |
|
200 free((void *) pathname); |
184 free((void *) pathname); |
201 pathname = NULL; |
185 pathname = NULL; |
|
186 if (tz != NULL) { |
|
187 break; |
|
188 } |
202 } |
189 } |
203 |
190 |
204 if (dirp != NULL) { |
191 if (dirp != NULL) { |
205 (void) closedir(dirp); |
192 (void) closedir(dirp); |
206 } |
193 } |
207 if (pathname != NULL) { |
194 return tz; |
208 free((void *) pathname); |
195 } |
209 } |
196 |
210 if (fd != -1) { |
197 /* |
|
198 * Checks if the file pointed to by pathname matches |
|
199 * the data contents in buf. |
|
200 * Returns a representation of the timezone file name |
|
201 * if file match is found, otherwise NULL. |
|
202 */ |
|
203 static char * |
|
204 isFileIdentical(char *buf, size_t size, char *pathname) |
|
205 { |
|
206 char *possibleMatch = NULL; |
|
207 struct stat64 statbuf; |
|
208 char *dbuf = NULL; |
|
209 int fd = -1; |
|
210 int res; |
|
211 |
|
212 RESTARTABLE(stat64(pathname, &statbuf), res); |
|
213 if (res == -1) { |
|
214 return NULL; |
|
215 } |
|
216 |
|
217 if (S_ISDIR(statbuf.st_mode)) { |
|
218 possibleMatch = findZoneinfoFile(buf, size, pathname); |
|
219 } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) { |
|
220 dbuf = (char *) malloc(size); |
|
221 if (dbuf == NULL) { |
|
222 return NULL; |
|
223 } |
|
224 RESTARTABLE(open(pathname, O_RDONLY), fd); |
|
225 if (fd == -1) { |
|
226 goto freedata; |
|
227 } |
|
228 RESTARTABLE(read(fd, dbuf, size), res); |
|
229 if (res != (ssize_t) size) { |
|
230 goto freedata; |
|
231 } |
|
232 if (memcmp(buf, dbuf, size) == 0) { |
|
233 possibleMatch = getZoneName(pathname); |
|
234 if (possibleMatch != NULL) { |
|
235 possibleMatch = strdup(possibleMatch); |
|
236 } |
|
237 } |
|
238 freedata: |
|
239 free((void *) dbuf); |
211 (void) close(fd); |
240 (void) close(fd); |
212 } |
241 } |
213 if (dbuf != NULL) { |
242 return possibleMatch; |
214 free((void *) dbuf); |
|
215 } |
|
216 return tz; |
|
217 } |
243 } |
218 |
244 |
219 #if defined(__linux__) || defined(MACOSX) |
245 #if defined(__linux__) || defined(MACOSX) |
220 |
246 |
221 /* |
247 /* |