Deleted Added
full compact
timelocal.c (72183) timelocal.c (72406)
1/*-
1/*-
2 * Copyright (c) 2001 Alexey Zelkin
2 * Copyright (c) 1997 FreeBSD Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.

--- 8 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
3 * Copyright (c) 1997 FreeBSD Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.

--- 8 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
26 * $FreeBSD: head/lib/libc/stdtime/timelocal.c 72183 2001-02-08 20:55:38Z ache $
27 * $FreeBSD: head/lib/libc/stdtime/timelocal.c 72406 2001-02-12 08:53:33Z phantom $
27 */
28
28 */
29
29#include "namespace.h"
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <sys/syslimits.h>
33#include <fcntl.h>
34#include <locale.h>
35#include <stddef.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include "un-namespace.h"
40
41#include "setlocale.h"
30#include "ldpart.h"
42#include "timelocal.h"
43
31#include "timelocal.h"
32
44static int split_lines(char *, const char *);
45static void set_from_buf(const char *, int);
46
47static struct lc_time_T _time_localebuf;
33static struct lc_time_T _time_locale;
48static int _time_using_locale;
34static int _time_using_locale;
35static char * time_locale_buf;
49
36
50#define LCTIME_SIZE_FULL (sizeof(struct lc_time_T) / sizeof(char *))
51#define LCTIME_SIZE_1 \
52 (offsetof(struct lc_time_T, alt_month[0]) / sizeof(char *))
53#define LCTIME_SIZE_2 \
54 (offsetof(struct lc_time_T, Ef_fmt) / sizeof(char *))
37#define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *))
55
56static const struct lc_time_T _C_time_locale = {
57 {
58 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
59 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
60 }, {
61 "January", "February", "March", "April", "May", "June",
62 "July", "August", "September", "October", "November", "December"

--- 45 unchanged lines hidden (view full) ---

108 ** To determine long months / day order
109 */
110 "%B %e"
111};
112
113struct lc_time_T *
114__get_current_time_locale(void) {
115 return (_time_using_locale
38
39static const struct lc_time_T _C_time_locale = {
40 {
41 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
42 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
43 }, {
44 "January", "February", "March", "April", "May", "June",
45 "July", "August", "September", "October", "November", "December"

--- 45 unchanged lines hidden (view full) ---

91 ** To determine long months / day order
92 */
93 "%B %e"
94};
95
96struct lc_time_T *
97__get_current_time_locale(void) {
98 return (_time_using_locale
116 ? &_time_localebuf
99 ? &_time_locale
117 : (struct lc_time_T *)&_C_time_locale);
118}
119
120int
100 : (struct lc_time_T *)&_C_time_locale);
101}
102
103int
121__time_load_locale(const char *name)
122{
123 static char * locale_buf;
124 static char locale_buf_C[] = "C";
125 static int num_lines;
104__time_load_locale(const char *name) {
126
105
127 int fd;
128 char * lbuf;
129 char * p;
130 const char * plim;
131 char filename[PATH_MAX];
132 struct stat st;
133 size_t namesize;
134 size_t bufsize;
135 int save_using_locale;
106 int ret;
136
107
137 save_using_locale = _time_using_locale;
138 _time_using_locale = 0;
108 ret = __part_load_locale(name, &_time_using_locale,
109 time_locale_buf, "LC_TIME", LCTIME_SIZE,
110 (const char **)&_time_locale);
139
111
140 if (name == NULL)
141 goto no_locale;
142
143 if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
144 return 0;
145
146 /*
147 ** If the locale name is the same as our cache, use the cache.
148 */
149 lbuf = locale_buf;
150 if (lbuf != NULL && strcmp(name, lbuf) == 0) {
151 set_from_buf(lbuf, num_lines);
152 _time_using_locale = 1;
153 return 0;
154 }
155 /*
156 ** Slurp the locale file into the cache.
157 */
158 namesize = strlen(name) + 1;
159
160 if (!_PathLocale)
161 goto no_locale;
162 /* Range checking not needed, 'name' size is limited */
163 strcpy(filename, _PathLocale);
164 strcat(filename, "/");
165 strcat(filename, name);
166 strcat(filename, "/LC_TIME");
167 fd = _open(filename, O_RDONLY);
168 if (fd < 0)
169 goto no_locale;
170 if (_fstat(fd, &st) != 0)
171 goto bad_locale;
172 if (st.st_size <= 0)
173 goto bad_locale;
174 bufsize = namesize + st.st_size;
175 locale_buf = NULL;
176 lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
177 malloc(bufsize) : reallocf(lbuf, bufsize);
178 if (lbuf == NULL)
179 goto bad_locale;
180 (void) strcpy(lbuf, name);
181 p = lbuf + namesize;
182 plim = p + st.st_size;
183 if (_read(fd, p, (size_t) st.st_size) != st.st_size)
184 goto bad_lbuf;
185 if (_close(fd) != 0)
186 goto bad_lbuf;
187 /*
188 ** Parse the locale file into localebuf.
189 */
190 if (plim[-1] != '\n')
191 goto bad_lbuf;
192 num_lines = split_lines(p, plim);
193 if (num_lines >= LCTIME_SIZE_FULL)
194 num_lines = LCTIME_SIZE_FULL;
195 else if (num_lines >= LCTIME_SIZE_2)
196 num_lines = LCTIME_SIZE_2;
197 else if (num_lines >= LCTIME_SIZE_1)
198 num_lines = LCTIME_SIZE_1;
199 else
200 goto reset_locale;
201 set_from_buf(lbuf, num_lines);
202 /*
203 ** Record the successful parse in the cache.
204 */
205 locale_buf = lbuf;
206
207 _time_using_locale = 1;
208 return 0;
209
210reset_locale:
211 /*
212 * XXX - This may not be the correct thing to do in this case.
213 * setlocale() assumes that we left the old locale alone.
214 */
215 locale_buf = locale_buf_C;
216 _time_localebuf = _C_time_locale;
217 save_using_locale = 0;
218bad_lbuf:
219 free(lbuf);
220bad_locale:
221 (void)_close(fd);
222no_locale:
223 _time_using_locale = save_using_locale;
224 return -1;
225}
226
227static int
228split_lines(char *p, const char *plim)
229{
230 int i;
231
232 for (i = 0; p < plim; i++) {
233 p = strchr(p, '\n');
234 *p++ = '\0';
235 }
236 return i;
237}
238
239static void
240set_from_buf(const char *p, int num_lines)
241{
242 const char **ap;
243 int i;
244
245 for (ap = (const char **) &_time_localebuf, i = 0;
246 i < num_lines; ++ap, ++i)
247 *ap = p += strlen(p) + 1;
248 /* XXX: always overwrite for ctime format parsing compatibility */
112 /* XXX: always overwrite for ctime format parsing compatibility */
249 _time_localebuf.c_fmt = _C_time_locale.c_fmt;
250 if (num_lines >= LCTIME_SIZE_2)
251 return;
252 for (i = 0; i < 12; i++)
253 _time_localebuf.alt_month[i] = _time_localebuf.month[i];
113 if (ret == 0 && _time_using_locale)
114 _time_locale.c_fmt = _C_time_locale.c_fmt;
115 return (ret);
254}
116}