This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Don't check ABI for _nl_default_dirname


Andreas Schwab wrote:

> The size is copied into the program by the COPY relocation.

Yep, that's why I didn't write a patch after reporting PR14664.

Are applications that use _nl_default_dirname buggy by definition
because its size can vary from machine to machine?  I'm inclined to
think "yes".  Is there anything we can do to make them behave better
anyway?

How about something like this?

diff --git i/intl/bindtextdom.c w/intl/bindtextdom.c
index 98a3606d..0ae6124b 100644
--- i/intl/bindtextdom.c
+++ w/intl/bindtextdom.c
@@ -45,7 +45,7 @@
    names than the internal variables in GNU libc, otherwise programs
    using libintl.a cannot be linked statically.  */
 #if !defined _LIBC
-# define _nl_default_dirname libintl_nl_default_dirname
+# define __nl_default_dirname libintl_nl_default_dirname
 # define _nl_domain_bindings libintl_nl_domain_bindings
 #endif
 
@@ -57,10 +57,7 @@
 /* @@ end of prolog @@ */
 
 /* Contains the default location of the message catalogs.  */
-extern const char _nl_default_dirname[];
-#ifdef _LIBC
-libc_hidden_proto (_nl_default_dirname)
-#endif
+extern const char __nl_default_dirname[] attribute_hidden;
 
 /* List with bindings of specific domains.  */
 extern struct binding *_nl_domain_bindings;
@@ -149,8 +146,8 @@ set_binding_values (domainname, dirnamep, codesetp)
 	      char *result = binding->dirname;
 	      if (strcmp (dirname, result) != 0)
 		{
-		  if (strcmp (dirname, _nl_default_dirname) == 0)
-		    result = (char *) _nl_default_dirname;
+		  if (strcmp (dirname, __nl_default_dirname) == 0)
+		    result = (char *) __nl_default_dirname;
 		  else
 		    {
 #if defined _LIBC || defined HAVE_STRDUP
@@ -165,7 +162,7 @@ set_binding_values (domainname, dirnamep, codesetp)
 
 		  if (__builtin_expect (result != NULL, 1))
 		    {
-		      if (binding->dirname != _nl_default_dirname)
+		      if (binding->dirname != __nl_default_dirname)
 			free (binding->dirname);
 
 		      binding->dirname = result;
@@ -217,7 +214,7 @@ set_binding_values (domainname, dirnamep, codesetp)
     {
       /* Simply return the default values.  */
       if (dirnamep)
-	*dirnamep = _nl_default_dirname;
+	*dirnamep = __nl_default_dirname;
       if (codesetp)
 	*codesetp = NULL;
     }
@@ -239,11 +236,11 @@ set_binding_values (domainname, dirnamep, codesetp)
 
 	  if (dirname == NULL)
 	    /* The default value.  */
-	    dirname = _nl_default_dirname;
+	    dirname = __nl_default_dirname;
 	  else
 	    {
-	      if (strcmp (dirname, _nl_default_dirname) == 0)
-		dirname = _nl_default_dirname;
+	      if (strcmp (dirname, __nl_default_dirname) == 0)
+		dirname = __nl_default_dirname;
 	      else
 		{
 		  char *result;
@@ -266,7 +263,7 @@ set_binding_values (domainname, dirnamep, codesetp)
 	}
       else
 	/* The default value.  */
-	new_binding->dirname = (char *) _nl_default_dirname;
+	new_binding->dirname = (char *) __nl_default_dirname;
 
       if (codesetp)
 	{
@@ -319,7 +316,7 @@ set_binding_values (domainname, dirnamep, codesetp)
       if (0)
 	{
 	failed_codeset:
-	  if (new_binding->dirname != _nl_default_dirname)
+	  if (new_binding->dirname != __nl_default_dirname)
 	    free (new_binding->dirname);
 	failed_dirname:
 	  free (new_binding);
diff --git i/intl/dcigettext.c w/intl/dcigettext.c
index 088fdcbd..eccf2270 100644
--- i/intl/dcigettext.c
+++ w/intl/dcigettext.c
@@ -105,7 +105,7 @@ extern int errno;
 #if !defined _LIBC
 # define _nl_default_default_domain libintl_nl_default_default_domain
 # define _nl_current_default_domain libintl_nl_current_default_domain
-# define _nl_default_dirname libintl_nl_default_dirname
+# define __nl_default_dirname libintl_nl_default_dirname
 # define _nl_domain_bindings libintl_nl_domain_bindings
 #endif
 
@@ -267,14 +267,22 @@ const char *_nl_current_default_domain attribute_hidden
      = _nl_default_default_domain;
 
 /* Contains the default location of the message catalogs.  */
+const char __nl_default_dirname[] attribute_hidden = LOCALEDIR;
 
+/* Historically, _nl_default_dirname was exported (though not advertised
+   in any headers).  Hopefully no one uses it.  Unfortunately anyone who
+   did use it has a COPY relocation that hard-codes the size.
+
+   The real _nl_default_dirname is now named __nl_default_dirname and is
+   private.  We export a separate _nl_default_dirname for compatibility
+   with a value that makes sense for prefix=/usr, which is the best one
+   could hope for given the ABI constraint.  */
 #ifdef _LIBC
 extern const char _nl_default_dirname[];
 libc_hidden_proto (_nl_default_dirname)
-#endif
-const char _nl_default_dirname[] = LOCALEDIR;
-#ifdef _LIBC
+const char _nl_default_dirname[] = "/usr/share/locale";
 libc_hidden_data_def (_nl_default_dirname)
+#define _nl_default_dirname _nl_default_dirname_dont_use_it
 #endif
 
 /* List with bindings of specific domains created by bindtextdomain()
@@ -524,7 +532,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
     }
 
   if (binding == NULL)
-    dirname = (char *) _nl_default_dirname;
+    dirname = (char *) __nl_default_dirname;
   else if (binding->dirname[0] == '/')
     dirname = binding->dirname;
   else
@@ -1452,7 +1460,7 @@ libc_freeres_fn (free_mem)
     {
       struct binding *oldp = _nl_domain_bindings;
       _nl_domain_bindings = _nl_domain_bindings->next;
-      if (oldp->dirname != _nl_default_dirname)
+      if (oldp->dirname != __nl_default_dirname)
 	/* Yes, this is a pointer comparison.  */
 	free (oldp->dirname);
       free (oldp->codeset);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]