Skip site navigation (1)Skip section navigation (2)
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>