+2025-02-14 Bruno Haible <bruno@clisp.org>
+
+ newlocale: Work around NetBSD bug.
+ * lib/newlocale.c (newlocale) [NetBSD]: Test whether the locale name is
+ valid; fail with error ENOENT if not.
+ * doc/posix-functions/newlocale.texi: Mention the NetBSD bug.
+
2025-02-14 Bruno Haible <bruno@clisp.org>
newlocale: Work around macOS, NetBSD, Solaris 11 OpenIndiana bug.
When the third argument is NULL, this function uses locale category data
from the current locale instead of from the "C" locale on some platforms:
macOS, NetBSD 10.0, Solaris 11 OpenIndiana.
+@item
+When the second argument is an invalid or unsupported locale name,
+this function uses the "C" locale instead of failing on some platforms:
+NetBSD 10.0.
@end itemize
Portability problems not fixed by Gnulib:
#if HAVE_NEWLOCALE
/* Only provide workarounds. */
+# include <sys/types.h>
+# include <sys/stat.h>
+
locale_t
newlocale (int category_mask, const char *name, locale_t base)
# undef newlocale
return NULL;
}
+# if defined __NetBSD__
+ /* Work around a NetBSD bug: newlocale does not fail (unlike setlocale)
+ when NAME is an invalid locale name. */
+ if (category_mask != 0)
+ {
+ /* Test whether NAME is valid. */
+ if (!(strcmp (name, "C") == 0 || strcmp (name, "POSIX") == 0))
+ {
+ char *filename = (char *) malloc (18 + strlen (name) + 9 + 1);
+ if (filename == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ sprintf (filename, "/usr/share/locale/%s/LC_CTYPE", name);
+ struct stat statbuf;
+ if (stat (filename, &statbuf) < 0)
+ {
+ free (filename);
+ errno = ENOENT;
+ return NULL;
+ }
+ free (filename);
+ }
+ }
+# endif
+
if (category_mask != LC_ALL_MASK && base == NULL)
base = newlocale (LC_ALL_MASK, "C", NULL);