summaryrefslogtreecommitdiffstats
path: root/lib/libc/locale/ldpart.c
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2002-08-08 05:51:54 +0000
committerache <ache@FreeBSD.org>2002-08-08 05:51:54 +0000
commit3b0ddae36e14f345ddbfb571d2838b236c78d073 (patch)
tree92e69228cb60dc54efe523b4a60905762797b926 /lib/libc/locale/ldpart.c
parenta72d8585b7d6c0e0b3cd0824b229a07724c33288 (diff)
downloadFreeBSD-src-3b0ddae36e14f345ddbfb571d2838b236c78d073.zip
FreeBSD-src-3b0ddae36e14f345ddbfb571d2838b236c78d073.tar.gz
Rewrite locale loading procedures, so any load failure will not affect
currently cached data. It allows a number of nice things, like: removing fallback code from single locale loading, remove memory leak when LC_CTYPE data loaded again and again, efficient cache use, not only for setlocale(locale1); setlocale(locale1), but for setlocale(locale1); setlocale("C"); setlocale(locale1) too (i.e. data file loaded only once).
Diffstat (limited to 'lib/libc/locale/ldpart.c')
-rw-r--r--lib/libc/locale/ldpart.c88
1 files changed, 31 insertions, 57 deletions
diff --git a/lib/libc/locale/ldpart.c b/lib/libc/locale/ldpart.c
index 0e276cf..1933312 100644
--- a/lib/libc/locale/ldpart.c
+++ b/lib/libc/locale/ldpart.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include "ldpart.h"
static int split_lines(char *, const char *);
-static void set_from_buf(const char *, int, const char **);
int
__part_load_locale(const char *name,
@@ -53,35 +52,25 @@ __part_load_locale(const char *name,
int locale_buf_size_min,
const char **dst_localebuf)
{
- static char locale_buf_C[] = "C";
- static int num_lines;
- int saverr;
- int fd;
- char *lbuf;
- char *p;
- const char *plim;
- char filename[PATH_MAX];
+ int saverr, fd, i, num_lines;
+ char *lbuf, *p;
+ const char *plim;
+ char filename[PATH_MAX];
struct stat st;
- size_t namesize;
- size_t bufsize;
- int save_using_locale;
-
- save_using_locale = *using_locale;
- *using_locale = 0;
+ size_t namesize, bufsize;
/* 'name' must be already checked. */
-
- if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
- return 0;
+ if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) {
+ *using_locale = 0;
+ return (_LDP_CACHE);
+ }
/*
* If the locale name is the same as our cache, use the cache.
*/
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- set_from_buf(lbuf, num_lines, dst_localebuf);
+ if (locale_buf != NULL && strcmp(name, locale_buf) == 0) {
*using_locale = 1;
- return 0;
+ return (_LDP_CACHE);
}
/*
@@ -90,16 +79,14 @@ __part_load_locale(const char *name,
namesize = strlen(name) + 1;
/* 'PathLocale' must be already set & checked. */
-
/* Range checking not needed, 'name' size is limited */
strcpy(filename, _PathLocale);
strcat(filename, "/");
strcat(filename, name);
strcat(filename, "/");
strcat(filename, category_filename);
- fd = _open(filename, O_RDONLY);
- if (fd < 0)
- goto no_locale;
+ if ((fd = _open(filename, O_RDONLY)) < 0)
+ return (_LDP_ERROR);
if (_fstat(fd, &st) != 0)
goto bad_locale;
if (st.st_size <= 0) {
@@ -107,18 +94,15 @@ __part_load_locale(const char *name,
goto bad_locale;
}
bufsize = namesize + st.st_size;
- locale_buf = NULL;
- lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
- malloc(bufsize) : reallocf(lbuf, bufsize);
- if (lbuf == NULL)
+ if ((lbuf = malloc(bufsize)) == NULL) {
+ errno = ENOMEM;
goto bad_locale;
+ }
(void)strcpy(lbuf, name);
p = lbuf + namesize;
plim = p + st.st_size;
if (_read(fd, p, (size_t) st.st_size) != st.st_size)
goto bad_lbuf;
- if (_close(fd) != 0)
- goto bad_lbuf;
/*
* Parse the locale file into localebuf.
*/
@@ -133,37 +117,37 @@ __part_load_locale(const char *name,
num_lines = locale_buf_size_min;
else {
errno = EFTYPE;
- goto reset_locale;
+ goto bad_lbuf;
}
- set_from_buf(lbuf, num_lines, dst_localebuf);
+ (void)_close(fd);
/*
* Record the successful parse in the cache.
*/
+ if (locale_buf != NULL)
+ free(locale_buf);
locale_buf = lbuf;
-
+ for (p = locale_buf, i = 0; i < num_lines; i++)
+ dst_localebuf[i] = (p += strlen(p) + 1);
+ for (i = num_lines; i < locale_buf_size_max; i++)
+ dst_localebuf[i] = NULL;
*using_locale = 1;
- return 0;
+ return (_LDP_LOADED);
-reset_locale:
- locale_buf = locale_buf_C;
- save_using_locale = 0;
bad_lbuf:
- saverr = errno;
- free(lbuf);
+ saverr = errno;
+ free(lbuf);
errno = saverr;
bad_locale:
- saverr = errno;
- (void)_close(fd);
+ saverr = errno;
+ (void)_close(fd);
errno = saverr;
-no_locale:
- *using_locale = save_using_locale;
- return -1;
+ return (_LDP_ERROR);
}
static int
-split_lines(char *p, const char *plim)
+split_lines(char *p, const char *plim)
{
int i;
@@ -174,13 +158,3 @@ split_lines(char *p, const char *plim)
return (i);
}
-static void
-set_from_buf(const char *p, int num_lines, const char **dst_localebuf) {
-
- const char **ap;
- int i;
-
- for (ap = dst_localebuf, i = 0; i < num_lines; ++ap, ++i)
- *ap = p += strlen(p) + 1;
-}
-
OpenPOWER on IntegriCloud