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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to