summary refs log tree commit diff
path: root/locale/programs
diff options
context:
space:
mode:
Diffstat (limited to 'locale/programs')
-rw-r--r--locale/programs/charmap.c2
-rw-r--r--locale/programs/ld-ctype.c47
-rw-r--r--locale/programs/locfile.c23
3 files changed, 37 insertions, 35 deletions
diff --git a/locale/programs/charmap.c b/locale/programs/charmap.c
index 35a6987fbc..7c013b24c3 100644
--- a/locale/programs/charmap.c
+++ b/locale/programs/charmap.c
@@ -1042,7 +1042,7 @@ hexadecimal range format should use only capital characters"));
 	  char *endp;
 
 	  errno = 0;
-	  newp->ucs4 = strtoul (name_end, &endp, 16);
+	  newp->ucs4 = strtoul (name_end + 1, &endp, 16);
 	  if (endp - name_end != len1
 	      || (newp->ucs4 == ULONG_MAX && errno == ERANGE)
 	      || newp->ucs4 >= 0x80000000)
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index 24a53919f2..e3f55644d3 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -116,6 +116,14 @@ struct translit_include_t
 };
 
 
+/* Sparse table of uint32_t.  */
+#define TABLE idx_table
+#define ELEMENT uint32_t
+#define DEFAULT ~((uint32_t) 0)
+#define NO_FINALIZE
+#include "3level.h"
+
+
 /* The real definition of the struct for the LC_CTYPE locale.  */
 struct locale_ctype_t
 {
@@ -123,8 +131,7 @@ struct locale_ctype_t
   size_t charnames_max;
   size_t charnames_act;
   /* An index lookup table, to speedup find_idx.  */
-#define MAX_CHARNAMES_IDX 0x10000
-  uint32_t *charnames_idx;
+  struct idx_table charnames_idx;
 
   struct repertoire_t *repertoire;
 
@@ -261,10 +268,7 @@ ctype_startup (struct linereader *lr, struct localedef_t *locale,
 	  for (cnt = 0; cnt < 256; ++cnt)
 	    ctype->charnames[cnt] = cnt;
 	  ctype->charnames_act = 256;
-	  ctype->charnames_idx =
-	    (uint32_t *) xmalloc (MAX_CHARNAMES_IDX * sizeof (uint32_t));
-	  for (cnt = 0; cnt < MAX_CHARNAMES_IDX; ++cnt)
-	    ctype->charnames_idx[cnt] = ~((uint32_t) 0);
+	  idx_table_init (&ctype->charnames_idx);
 
 	  /* Fill character class information.  */
 	  ctype->last_class_char = ILLEGAL_CHAR_VALUE;
@@ -1280,23 +1284,17 @@ find_idx (struct locale_ctype_t *ctype, uint32_t **table, size_t *max,
   if (idx < 256)
     return table == NULL ? NULL : &(*table)[idx];
 
-  /* If idx is in the usual range, use the charnames_idx lookup table
-     instead of the slow search loop.  */
-  if (idx < MAX_CHARNAMES_IDX)
-    {
-      if (ctype->charnames_idx[idx] != ~((uint32_t) 0))
-	/* Found.  */
-	cnt = ctype->charnames_idx[idx];
-      else
-	/* Not found.  */
-	cnt = ctype->charnames_act;
-    }
-  else
-    {
-      for (cnt = 256; cnt < ctype->charnames_act; ++cnt)
-	if (ctype->charnames[cnt] == idx)
-	  break;
-    }
+  /* Use the charnames_idx lookup table instead of the slow search loop.  */
+#if 1
+  cnt = idx_table_get (&ctype->charnames_idx, idx);
+  if (cnt == ~((uint32_t) 0))
+    /* Not found.  */
+    cnt = ctype->charnames_act;
+#else
+  for (cnt = 256; cnt < ctype->charnames_act; ++cnt)
+    if (ctype->charnames[cnt] == idx)
+      break;
+#endif
 
   /* We have to distinguish two cases: the name is found or not.  */
   if (cnt == ctype->charnames_act)
@@ -1310,8 +1308,7 @@ find_idx (struct locale_ctype_t *ctype, uint32_t **table, size_t *max,
 		      sizeof (uint32_t) * ctype->charnames_max);
 	}
       ctype->charnames[ctype->charnames_act++] = idx;
-      if (idx < MAX_CHARNAMES_IDX)
-	ctype->charnames_idx[idx] = cnt;
+      idx_table_add (&ctype->charnames_idx, idx, cnt);
     }
 
   if (table == NULL)
diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
index 7c724e292f..185ccbc77f 100644
--- a/locale/programs/locfile.c
+++ b/locale/programs/locfile.c
@@ -338,30 +338,33 @@ write_locale_data (const char *output_path, const char *category,
      data.  This means we need to have a directory LC_MESSAGES in
      which we place the file under the name SYS_LC_MESSAGES.  */
   sprintf (fname, "%s%s", output_path, category);
+  fd = -2;
   if (strcmp (category, "LC_MESSAGES") == 0)
     {
       struct stat st;
 
       if (stat (fname, &st) < 0)
 	{
-	  if (mkdir (fname, 0777) < 0)
-	    fd = creat (fname, 0666);
-	  else
+	  if (mkdir (fname, 0777) >= 0)
 	    {
 	      fd = -1;
 	      errno = EISDIR;
 	    }
 	}
-      else if (S_ISREG (st.st_mode))
-	fd = creat (fname, 0666);
-      else
+      else if (!S_ISREG (st.st_mode))
 	{
 	  fd = -1;
 	  errno = EISDIR;
 	}
     }
-  else
-    fd = creat (fname, 0666);
+
+  /* Create the locale file with nlinks == 1; this avoids crashing processes
+     which currently use the locale.  */
+  if (fd == -2)
+    {
+      unlink (fname);
+      fd = creat (fname, 0666);
+    }
 
   if (fd == -1)
     {
@@ -369,7 +372,8 @@ write_locale_data (const char *output_path, const char *category,
 
       if (errno == EISDIR)
 	{
-	  sprintf (fname, "%1$s/%2$s/SYS_%2$s", output_path, category);
+	  sprintf (fname, "%1$s%2$s/SYS_%2$s", output_path, category);
+	  unlink (fname);
 	  fd = creat (fname, 0666);
 	  if (fd == -1)
 	    save_err = errno;
@@ -381,6 +385,7 @@ write_locale_data (const char *output_path, const char *category,
 	    error (0, save_err, _("\
 cannot open output file `%s' for category `%s'"),
 		   fname, category);
+	  free (fname);
 	  return;
 	}
     }