Date: Tue, 9 Feb 2010 19:37:12 +0000 (UTC) From: Gabor Kovesdan <gabor@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r203719 - head/lib/libc/nls Message-ID: <201002091937.o19JbCm6061778@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gabor Date: Tue Feb 9 19:37:12 2010 New Revision: 203719 URL: http://svn.freebsd.org/changeset/base/203719 Log: - Deal with some special cases [1] - style(9) nits Pointed out by: jilles [1] Approved by: delphij (mentor) Modified: head/lib/libc/nls/msgcat.c Modified: head/lib/libc/nls/msgcat.c ============================================================================== --- head/lib/libc/nls/msgcat.c Tue Feb 9 19:27:54 2010 (r203718) +++ head/lib/libc/nls/msgcat.c Tue Feb 9 19:37:12 2010 (r203719) @@ -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 /* 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 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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002091937.o19JbCm6061778>