summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authorsp149894 <none@none>2007-06-12 02:38:27 -0700
committersp149894 <none@none>2007-06-12 02:38:27 -0700
commite53d4db11f7999d0e42405e94c04e1c2e54be0b5 (patch)
tree1fa5ca25b4a26b8bfb75b1908f989383fd98f9a3 /usr/src/lib/libc
parent273e557d0fef8a74039398d861ac01dafddba60f (diff)
downloadillumos-joyent-e53d4db11f7999d0e42405e94c04e1c2e54be0b5.tar.gz
6293320 gettxt() not MT-SAFE
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r--usr/src/lib/libc/port/gen/gettxt.c242
-rw-r--r--usr/src/lib/libc/port/gen/gtxt.c24
2 files changed, 130 insertions, 136 deletions
diff --git a/usr/src/lib/libc/port/gen/gettxt.c b/usr/src/lib/libc/port/gen/gettxt.c
index c9b1d386e3..2399f92f89 100644
--- a/usr/src/lib/libc/port/gen/gettxt.c
+++ b/usr/src/lib/libc/port/gen/gettxt.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,6 +33,8 @@
#pragma weak gettxt = _gettxt
#include "synonyms.h"
+#include "libc.h"
+#include <mtlib.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
@@ -46,172 +47,165 @@
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
+#include <thread.h>
#include "../i18n/_locale.h"
#include "../i18n/_loc_path.h"
-#define MAXDB 10 /* maximum number of data bases per program */
#define MESSAGES "/LC_MESSAGES/"
#define DB_NAME_LEN 15
-char *handle_return(const char *);
+#define handle_return(s) \
+ ((char *)((s) != NULL && *(s) != '\0' ? (s) : not_found))
-/* support multiple versions of a package */
+extern char cur_cat[];
+extern rwlock_t _rw_cur_cat;
-char *Msgdb = (char *)NULL;
+static mutex_t gettxt_lock = DEFAULTMUTEX;
+static const char *not_found = "Message not found!!\n";
+static const char *loc_C = "C";
-static char *saved_locale = NULL;
-static const char *not_found = "Message not found!!\n";
-
-static struct db_info {
+struct db_list {
char db_name[DB_NAME_LEN]; /* name of the message file */
uintptr_t addr; /* virtual memory address */
- size_t length;
-} *db_info;
+ struct db_list *next;
+};
+
+struct db_cache {
+ char *loc;
+ struct db_list *info;
+ struct db_cache *next;
+};
-static int db_count; /* number of currently accessible data bases */
+static struct db_cache *db_cache;
char *
gettxt(const char *msg_id, const char *dflt_str)
{
- char msgfile[DB_NAME_LEN]; /* name of static shared library */
- int msgnum; /* message number */
- char pathname[PATH_MAX]; /* full pathname to message file */
- int i;
- int new_locale = 0;
- int fd;
- struct stat64 sb;
+ struct db_cache *dbc;
+ struct db_list *dbl;
+ char msgfile[DB_NAME_LEN]; /* name of static shared library */
+ int msgnum; /* message number */
+ char pathname[PATH_MAX]; /* full pathname to message file */
+ int fd;
+ struct stat64 sb;
void *addr;
- char *tokp;
- size_t name_len;
+ char *tokp;
+ size_t name_len;
char *curloc;
- if ((msg_id == NULL) || (*msg_id == NULL)) {
+ if ((msg_id == NULL) || (*msg_id == '\0')) {
return (handle_return(dflt_str));
}
- /* first time called, allocate space */
- if (!db_info) {
- if ((db_info = (struct db_info *) \
- malloc(MAXDB * sizeof (struct db_info))) == NULL)
- return (handle_return(dflt_str));
- }
-
/* parse msg_id */
-
if (((tokp = strchr(msg_id, ':')) == NULL) || *(tokp+1) == '\0')
return (handle_return(dflt_str));
if ((name_len = (tokp - msg_id)) >= DB_NAME_LEN)
return (handle_return(dflt_str));
- if (name_len) {
+ if (name_len > 0) {
(void) strncpy(msgfile, msg_id, name_len);
msgfile[name_len] = '\0';
} else {
- if (Msgdb && strlen(Msgdb) < DB_NAME_LEN)
- (void) strcpy(msgfile, Msgdb);
- else {
- char *p;
- p = (char *)setcat((const char *)0);
- if ((p != NULL) && strlen(p) < DB_NAME_LEN)
- (void) strcpy(msgfile, p);
- else
- return (handle_return(dflt_str));
+ lrw_rdlock(&_rw_cur_cat);
+ if (cur_cat == NULL || *cur_cat == '\0') {
+ lrw_unlock(&_rw_cur_cat);
+ return (handle_return(dflt_str));
}
+ /*
+ * We know the following strcpy is safe.
+ */
+ (void) strcpy(msgfile, cur_cat);
+ lrw_unlock(&_rw_cur_cat);
}
- while (*++tokp)
- if (!isdigit(*tokp))
+ while (*++tokp) {
+ if (!isdigit((unsigned char)*tokp))
return (handle_return(dflt_str));
+ }
msgnum = atoi(msg_id + name_len + 1);
-
- /* Has locale been changed? */
-
curloc = setlocale(LC_MESSAGES, NULL);
- if (saved_locale != NULL && strcmp(curloc, saved_locale) == 0) {
- for (i = 0; i < db_count; i++)
- if (strcmp(db_info[i].db_name, msgfile) == 0)
- break;
- } else { /* new locale - clear everything */
- if (saved_locale)
- free(saved_locale);
- /*
- * allocate at least 2 bytes, so that we can copy "C"
- * without re-allocating the saved_locale.
- */
- if ((saved_locale = malloc(strlen(curloc)+2)) == NULL)
- return (handle_return(dflt_str));
- (void) strcpy(saved_locale, curloc);
- for (i = 0; i < db_count; i++) {
- (void) munmap((void *)db_info[i].addr,
- db_info[i].length);
- (void) strcpy(db_info[i].db_name, "");
- new_locale++;
+
+ lmutex_lock(&gettxt_lock);
+
+try_C:
+ dbc = db_cache;
+ while (dbc) {
+ if (strcmp(curloc, dbc->loc) == 0) {
+ dbl = dbc->info;
+ while (dbl) {
+ if (strcmp(msgfile, dbl->db_name) == 0) {
+ /* msgfile found */
+ lmutex_unlock(&gettxt_lock);
+ goto msgfile_found;
+ }
+ dbl = dbl->next;
+ }
+ /* not found */
+ break;
}
- db_count = 0;
+ dbc = dbc->next;
}
- if (new_locale || i == db_count) {
- if (db_count == MAXDB)
+ if (dbc == NULL) {
+ /* new locale */
+ if ((dbc = lmalloc(sizeof (struct db_cache))) == NULL) {
+ lmutex_unlock(&gettxt_lock);
return (handle_return(dflt_str));
- if (snprintf(pathname, sizeof (pathname),
- _DFLT_LOC_PATH "%s" MESSAGES "%s",
- saved_locale, msgfile) >= sizeof (pathname)) {
+ }
+ if ((dbc->loc = lmalloc(strlen(curloc) + 1)) == NULL) {
+ lfree(dbc, sizeof (struct db_cache));
+ lmutex_unlock(&gettxt_lock);
return (handle_return(dflt_str));
}
- if ((fd = open(pathname, O_RDONLY)) == -1 ||
- fstat64(fd, &sb) == -1 ||
- (addr = mmap(0, (size_t)sb.st_size,
- PROT_READ, MAP_SHARED,
- fd, 0)) == MAP_FAILED) {
- if (fd != -1)
- (void) close(fd);
- if (strcmp(saved_locale, "C") == 0)
- return (handle_return(dflt_str));
-
- /* Change locale to C */
-
- if (snprintf(pathname, sizeof (pathname),
- _DFLT_LOC_PATH "C" MESSAGES "%s",
- msgfile) >= sizeof (pathname)) {
- return (handle_return(dflt_str));
- }
+ dbc->info = NULL;
+ (void) strcpy(dbc->loc, curloc);
+ /* connect dbc to the dbc list */
+ dbc->next = db_cache;
+ db_cache = dbc;
+ }
+ if ((dbl = lmalloc(sizeof (struct db_list))) == NULL) {
+ lmutex_unlock(&gettxt_lock);
+ return (handle_return(dflt_str));
+ }
- for (i = 0; i < db_count; i++) {
- (void) munmap((void *)db_info[i].addr,
- db_info[i].length);
- (void) strcpy(db_info[i].db_name, "");
- }
- db_count = 0;
- if ((fd = open(pathname, O_RDONLY)) != -1 &&
- fstat64(fd, &sb) != -1 &&
- (addr = mmap(0, (size_t)sb.st_size,
- PROT_READ, MAP_SHARED,
- fd, 0)) != MAP_FAILED) {
- (void) strcpy(saved_locale, "C");
- } else {
- if (fd != -1)
- (void) close(fd);
- return (handle_return(dflt_str));
- }
- }
+ if (snprintf(pathname, sizeof (pathname),
+ _DFLT_LOC_PATH "%s" MESSAGES "%s", dbc->loc, msgfile) >=
+ sizeof (pathname)) {
+ lfree(dbl, sizeof (struct db_list));
+ lmutex_unlock(&gettxt_lock);
+ return (handle_return(dflt_str));
+ }
+ if ((fd = open(pathname, O_RDONLY)) == -1 ||
+ fstat64(fd, &sb) == -1 ||
+ (addr = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
+ fd, 0L)) == MAP_FAILED) {
if (fd != -1)
(void) close(fd);
+ lfree(dbl, sizeof (struct db_list));
- /* save file name, memory address, fd and size */
-
- (void) strcpy(db_info[db_count].db_name, msgfile);
- db_info[db_count].addr = (uintptr_t)addr;
- db_info[db_count].length = (size_t)sb.st_size;
- i = db_count;
- db_count++;
+ if (strcmp(dbc->loc, "C") == 0) {
+ lmutex_unlock(&gettxt_lock);
+ return (handle_return(dflt_str));
+ }
+ /* Change locale to C */
+ curloc = (char *)loc_C;
+ goto try_C;
}
+ (void) close(fd);
+
+ /* save file name, memory address, fd and size */
+ (void) strcpy(dbl->db_name, msgfile);
+ dbl->addr = (uintptr_t)addr;
+
+ /* connect dbl to the dbc->info list */
+ dbl->next = dbc->info;
+ dbc->info = dbl;
+
+ lmutex_unlock(&gettxt_lock);
+
+msgfile_found:
/* check if msgnum out of domain */
- if (msgnum <= 0 || msgnum > *(int *)(db_info[i].addr))
+ if (msgnum <= 0 || msgnum > *(int *)dbl->addr)
return (handle_return(dflt_str));
/* return pointer to message */
- return ((char *)(db_info[i].addr + *(int *)(db_info[i].addr
- + msgnum * sizeof (int))));
-}
-
-char *
-handle_return(const char *dflt_str)
-{
- return ((char *)(dflt_str && *dflt_str ? dflt_str : not_found));
+ return ((char *)(dbl->addr +
+ *(int *)(dbl->addr + msgnum * sizeof (int))));
}
diff --git a/usr/src/lib/libc/port/gen/gtxt.c b/usr/src/lib/libc/port/gen/gtxt.c
index ad39860959..145743bdd8 100644
--- a/usr/src/lib/libc/port/gen/gtxt.c
+++ b/usr/src/lib/libc/port/gen/gtxt.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -73,8 +73,8 @@ struct db_info {
/* Minimum number of open catalogues */
#define MINDB 3
-static char cur_cat[DB_NAME_LEN];
-static rwlock_t _rw_cur_cat = DEFAULTRWLOCK;
+char cur_cat[DB_NAME_LEN];
+rwlock_t _rw_cur_cat = DEFAULTRWLOCK;
/*
@@ -151,8 +151,8 @@ load_db(const char *curloc, const char *catname, int *err)
}
db->flag = DB_OPEN;
if (snprintf(pathname, sizeof (pathname),
- _DFLT_LOC_PATH "%s" MESSAGES "%s",
- db->saved_locale, db->db_name) >= sizeof (pathname)) {
+ _DFLT_LOC_PATH "%s" MESSAGES "%s",
+ db->saved_locale, db->db_name) >= sizeof (pathname)) {
/*
* We won't set err here, because an invalid locale is not
* the fatal condition, but we can fall back to "C"
@@ -161,9 +161,9 @@ load_db(const char *curloc, const char *catname, int *err)
return (NULL);
}
if ((fd = open(pathname, O_RDONLY)) != -1 &&
- fstat64(fd, &sb) != -1 &&
- (addr = mmap(0, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
- fd, 0)) != MAP_FAILED) {
+ fstat64(fd, &sb) != -1 &&
+ (addr = mmap(0, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
+ fd, 0)) != MAP_FAILED) {
db->flag |= DB_EXIST;
db->addr = (uintptr_t)addr;
db->length = (size_t)sb.st_size;
@@ -180,7 +180,7 @@ static void
unload_db(struct db_info *db)
{
if ((db->flag & (DB_OPEN|DB_EXIST)) ==
- (DB_OPEN|DB_EXIST)) {
+ (DB_OPEN|DB_EXIST)) {
(void) munmap((caddr_t)db->addr, db->length);
}
db->flag = 0;
@@ -213,8 +213,8 @@ lookup_cache(struct db_info *db, const char *curloc, const char *catname)
continue;
if (strcmp(db->db_name, catname) == 0) {
if (curloc == NULL ||
- (db->saved_locale != NULL &&
- strcmp(db->saved_locale, curloc) == 0)) {
+ (db->saved_locale != NULL &&
+ strcmp(db->saved_locale, curloc) == 0)) {
return (db);
}
}
@@ -240,7 +240,7 @@ static char *
msg(struct db_info *db, int id)
{
return ((char *)(db->addr + *(int *)(db->addr +
- id * sizeof (int))));
+ id * sizeof (int))));
}
/*