summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorgabor <gabor@FreeBSD.org>2010-02-09 19:37:12 +0000
committergabor <gabor@FreeBSD.org>2010-02-09 19:37:12 +0000
commit4081d06fa6ef05970d77dcfc0971dfceeba868cc (patch)
tree441b8fb60e93cd6b841169cb2955ce9eab84cd11 /lib
parentb472b223d55e56bfb800652dc279d79a7ce13ecd (diff)
downloadFreeBSD-src-4081d06fa6ef05970d77dcfc0971dfceeba868cc.zip
FreeBSD-src-4081d06fa6ef05970d77dcfc0971dfceeba868cc.tar.gz
- Deal with some special cases [1]
- style(9) nits Pointed out by: jilles [1] Approved by: delphij (mentor)
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/nls/msgcat.c84
1 files changed, 54 insertions, 30 deletions
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
index 0b008ea..910c185 100644
--- a/lib/libc/nls/msgcat.c
+++ b/lib/libc/nls/msgcat.c
@@ -77,19 +77,22 @@ __FBSDID("$FreeBSD$");
#define NLERR ((nl_catd) -1)
#define NLRETERR(errc) { errno = errc; return (NLERR); }
-#define SAVEFAIL(n, e) { WLOCK(NLERR); \
- np = malloc(sizeof(struct catentry)); \
- if (np != NULL) { \
- np->name = strdup(n); \
- np->caterrno = e; \
- SLIST_INSERT_HEAD(&cache, np, list); \
- } \
- UNLOCK; \
- }
+#define SAVEFAIL(n, l, e) { WLOCK(NLERR); \
+ np = malloc(sizeof(struct catentry)); \
+ if (np != NULL) { \
+ np->name = strdup(n); \
+ np->path = NULL; \
+ np->lang = (l == NULL) ? NULL : strdup(l); \
+ np->caterrno = e; \
+ SLIST_INSERT_HEAD(&cache, np, list); \
+ } \
+ UNLOCK; \
+ errno = e; \
+ }
static nl_catd load_msgcat(const char *, const char *, const char *);
-static pthread_rwlock_t rwlock;
+static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
struct catentry {
SLIST_ENTRY(catentry) list;
@@ -114,10 +117,12 @@ catopen(const char *name, int type)
int saverr, spcleft;
char path[PATH_MAX];
+ /* sanity checking */
if (name == NULL || *name == '\0')
NLRETERR(EINVAL);
if (strchr(name, '/') != NULL)
+ /* have a pathname */
lang = NULL;
else {
if (type == NL_CAT_LOCALE)
@@ -135,12 +140,14 @@ catopen(const char *name, int type)
/* Try to get it from the cache first */
RLOCK(NLERR);
SLIST_FOREACH(np, &cache, list) {
- if (strcmp(np->name, name) == 0) {
+ if ((strcmp(np->name, name) == 0) &&
+ ((lang != NULL && np->lang != NULL &&
+ strcmp(np->lang, lang) == 0) || (np->lang == lang))) {
if (np->caterrno != 0) {
/* Found cached failing entry */
UNLOCK;
NLRETERR(np->caterrno);
- } else if (strcmp(np->lang, lang) == 0) {
+ } else {
/* Found cached successful entry */
np->refcount++;
UNLOCK;
@@ -154,6 +161,7 @@ catopen(const char *name, int type)
if (strchr(name, '/') != NULL)
return (load_msgcat(name, name, lang));
+ /* sanity checking */
if ((plang = cptr1 = strdup(lang)) == NULL)
return (NLERR);
if ((cptr = strchr(cptr1, '@')) != NULL)
@@ -218,6 +226,7 @@ catopen(const char *name, int type)
too_long:
free(plang);
free(base);
+ SAVEFAIL(name, lang, ENAMETOOLONG);
NLRETERR(ENAMETOOLONG);
}
pathP += strlen(tmpptr);
@@ -241,6 +250,7 @@ catopen(const char *name, int type)
}
free(plang);
free(base);
+ SAVEFAIL(name, lang, ENOENT);
NLRETERR(ENOENT);
}
@@ -317,6 +327,7 @@ catclose(nl_catd catd)
{
struct catentry *np;
+ /* sanity checking */
if (catd == NULL || catd == NLERR) {
errno = EBADF;
return (-1);
@@ -325,13 +336,15 @@ catclose(nl_catd catd)
/* Remove from cache if not referenced any more */
WLOCK(-1);
SLIST_FOREACH(np, &cache, list) {
- if ((np->catd->__size == catd->__size) &&
- memcmp((const void *)np->catd, (const void *)catd, np->catd->__size) == 0) {
+ if (catd == np->catd) {
np->refcount--;
if (np->refcount == 0) {
munmap(catd->__data, (size_t)catd->__size);
free(catd);
SLIST_REMOVE(&cache, np, catentry, list);
+ free(np->name);
+ free(np->path);
+ free(np->lang);
free(np);
}
break;
@@ -357,10 +370,11 @@ load_msgcat(const char *path, const char *name, const char *lang)
/* path/name will never be NULL here */
/* One more try in cache; if it was not found by name,
- it might still be found by absolute path. */
+ * it might still be found by absolute path.
+ */
RLOCK(NLERR);
SLIST_FOREACH(np, &cache, list) {
- if (strcmp(np->path, path) == 0) {
+ if ((np->path != NULL) && (strcmp(np->path, path) == 0)) {
np->refcount++;
UNLOCK;
return (np->catd);
@@ -369,36 +383,46 @@ load_msgcat(const char *path, const char *name, const char *lang)
UNLOCK;
if ((fd = _open(path, O_RDONLY)) == -1) {
- SAVEFAIL(name, errno);
- return (NLERR);
+ SAVEFAIL(name, lang, errno);
+ NLRETERR(errno);
}
if (_fstat(fd, &st) != 0) {
- SAVEFAIL(name, errno);
_close(fd);
- return (NLERR);
+ SAVEFAIL(name, lang, EFTYPE);
+ NLRETERR(EFTYPE);
}
- data = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd,
- (off_t)0);
- _close(fd);
+ /* If the file size cannot be held in size_t we cannot mmap()
+ * it to the memory. Probably, this will not be a problem given
+ * that catalog files are usually small.
+ */
+ if (st.st_size > SIZE_T_MAX) {
+ _close(fd);
+ SAVEFAIL(name, lang, EFBIG);
+ NLRETERR(EFBIG);
+ }
- if (data == MAP_FAILED) {
- SAVEFAIL(name, errno);
- return (NLERR);
+ if ((data = mmap(0, (size_t)st.st_size, PROT_READ,
+ MAP_FILE|MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
+ int saved_errno = errno;
+ _close(fd);
+ SAVEFAIL(name, lang, saved_errno);
+ NLRETERR(saved_errno);
}
+ _close(fd);
if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
_NLS_MAGIC) {
- SAVEFAIL(name, errno);
munmap(data, (size_t)st.st_size);
- NLRETERR(EINVAL);
+ SAVEFAIL(name, lang, EFTYPE);
+ NLRETERR(EFTYPE);
}
if ((catd = malloc(sizeof (*catd))) == NULL) {
- SAVEFAIL(name, errno);
munmap(data, (size_t)st.st_size);
- return (NLERR);
+ SAVEFAIL(name, lang, ENOMEM);
+ NLRETERR(ENOMEM);
}
catd->__data = data;
OpenPOWER on IntegriCloud