[gnome-desktop] Obtain supported locales from "locale -a" output.



commit 91082e8d0ef7dc3fe372fb5228fd3bb5a26efa81
Author: Stefan Sperling <stsp openbsd org>
Date:   Wed Aug 28 18:25:34 2013 +0200

    Obtain supported locales from "locale -a" output.
    
    Instead of parsing the locale archive file which is private to glibc
    (see https://bugzilla.redhat.com/show_bug.cgi?id=956993), run the
    "locale -a" command to obtain the list of supported locales.
    
    "locale -a" is specified in POSIX and should thus exist on most UNIX-like
    systems (e.g. on OpenBSD, which triggered the related bugzilla entry
    because GNOME was unable to find a list of supported locales).
    
    Keep scanning the /usr/share/locale directory as a fallback.
    
    Remove code wrapped in #ifdef WITH_INCOMPLETE_LOCALES. This code was
    inherited from gdm but is now unused.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=698383

 libgnome-desktop/gnome-languages.c |  150 ++++++++---------------------------
 1 files changed, 35 insertions(+), 115 deletions(-)
---
diff --git a/libgnome-desktop/gnome-languages.c b/libgnome-desktop/gnome-languages.c
index 18e3705..667eb81 100644
--- a/libgnome-desktop/gnome-languages.c
+++ b/libgnome-desktop/gnome-languages.c
@@ -44,10 +44,7 @@
 #ifndef __LC_LAST
 #define __LC_LAST       13
 #endif
-#include "locarchive.h"
 
-#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
-#define SYSTEM_ARCHIVE_FILE "/usr/lib/locale/locale-archive"
 #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
 
@@ -310,11 +307,7 @@ language_name_is_valid (const char *language_name)
 {
         char     *old_locale;
         gboolean  is_valid;
-#ifdef WITH_INCOMPLETE_LOCALES
-        int lc_type_id = LC_CTYPE;
-#else
         int lc_type_id = LC_MESSAGES;
-#endif
 
         old_locale = g_strdup (setlocale (lc_type_id, NULL));
         is_valid = setlocale (lc_type_id, language_name) != NULL;
@@ -445,22 +438,11 @@ add_locale (const char *language_name,
         g_free (name);
         name = NULL;
 
-#ifdef WITH_INCOMPLETE_LOCALES
-        if (utf8_only) {
-                if (locale->territory_code == NULL || locale->modifier) {
-                        g_debug ("Ignoring '%s' as a locale, since it lacks territory code or modifier", 
name);
-                        gnome_locale_free (locale);
-                        return FALSE;
-                }
-        }
-#endif
-
         locale->id = construct_language_name (locale->language_code, locale->territory_code,
                                               NULL, locale->modifier);
         locale->name = construct_language_name (locale->language_code, locale->territory_code,
                                                 locale->codeset, locale->modifier);
 
-#ifndef WITH_INCOMPLETE_LOCALES
         if (!gnome_language_has_translations (locale->name) &&
             !gnome_language_has_translations (locale->id) &&
             !gnome_language_has_translations (locale->language_code) &&
@@ -469,7 +451,6 @@ add_locale (const char *language_name,
                 gnome_locale_free (locale);
                 return FALSE;
         }
-#endif
 
         if (!utf8_only) {
                 g_free (locale->id);
@@ -492,94 +473,9 @@ add_locale (const char *language_name,
 struct nameent
 {
         char    *name;
-        uint32_t locrec_offset;
+        guint32 locrec_offset;
 };
 
-static gboolean
-mapped_file_new_allow_noent (const char   *path,
-                             GMappedFile **out_mfile,
-                             GError      **error)
-{
-        gboolean ret = FALSE;
-        GError *tmp_error = NULL;
-        GMappedFile *mfile = NULL;
-
-        mfile = g_mapped_file_new (path, FALSE, &tmp_error);
-        if (mfile == NULL) {
-                if (!g_error_matches (tmp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
-                        g_propagate_error (error, tmp_error);
-                        goto out;
-                }
-                g_clear_error (&tmp_error);
-        }
-
-        ret = TRUE;
- out:
-        *out_mfile = mfile;
-        return ret;
-}
-
-static gboolean
-collect_locales_from_archive (gboolean  *out_found_locales,
-                              GError   **error)
-{
-        gboolean            ret = FALSE;
-        GMappedFile        *mapped;
-        char               *addr;
-        struct locarhead   *head;
-        struct namehashent *namehashtab;
-        struct nameent     *names = NULL;
-        uint32_t            used;
-        uint32_t            cnt;
-        gsize               len;
-        gboolean            locales_collected = FALSE;
-
-        if (!mapped_file_new_allow_noent (ARCHIVE_FILE, &mapped, error))
-                goto out;
-        if (!mapped) {
-                if (!mapped_file_new_allow_noent (SYSTEM_ARCHIVE_FILE, &mapped, error))
-                        goto out;
-        }
-        if (!mapped) {
-                goto out_success;
-        }
-
-        addr = g_mapped_file_get_contents (mapped);
-        len = g_mapped_file_get_length (mapped);
-
-        head = (struct locarhead *) addr;
-        if (head->namehash_offset + head->namehash_size > len
-            || head->string_offset + head->string_size > len
-            || head->locrectab_offset + head->locrectab_size > len
-            || head->sumhash_offset + head->sumhash_size > len) {
-                goto out;
-        }
-
-        namehashtab = (struct namehashent *) (addr + head->namehash_offset);
-
-        names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
-        for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
-                if (namehashtab[cnt].locrec_offset != 0) {
-                        names[used].name = addr + namehashtab[cnt].name_offset;
-                        names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
-                }
-        }
-
-        for (cnt = 0; cnt < used; ++cnt) {
-                if (add_locale (names[cnt].name, TRUE))
-                        locales_collected = TRUE;
-        }
-
-
- out_success:
-        ret = TRUE;
-        *out_found_locales = locales_collected;
- out:
-        g_free (names);
-        g_clear_pointer (&mapped, g_mapped_file_unref);
-        return ret;
-}
-
 static int
 select_dirs (const struct dirent *dirent)
 {
@@ -631,6 +527,37 @@ collect_locales_from_directory (void)
         return found_locales;
 }
 
+static gboolean
+collect_locales_from_localebin (void)
+{
+        gboolean found_locales = FALSE;
+        gchar    *argv[] = { "locale", "-a", NULL };
+        gchar    *output;
+        gchar    **lines, **linep;
+
+        if (g_spawn_sync (NULL, argv, NULL,
+                          G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
+                          NULL, NULL, &output, NULL, NULL, NULL) == FALSE)
+                return FALSE;
+
+        g_return_val_if_fail (output != NULL, FALSE);
+
+        lines = g_strsplit (output, "\n", 0);
+        if (lines) {
+                linep = lines;
+                while (*linep) {
+                        if (*linep[0] && add_locale (*linep, TRUE))
+                                found_locales = TRUE;
+                        linep++;
+                }
+                g_strfreev(lines);
+        }
+
+        g_free(output);
+
+        return found_locales;
+}
+
 static void
 count_languages_and_territories (void)
 {
@@ -667,28 +594,21 @@ count_languages_and_territories (void)
 static void
 collect_locales (void)
 {
-        gboolean found_archive_locales = FALSE;
+        gboolean found_localebin_locales = FALSE;
         gboolean found_dir_locales = FALSE;
-        GError *error = NULL;
 
         if (gnome_available_locales_map == NULL) {
                 gnome_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) gnome_locale_free);
         }
 
-
-        if (!collect_locales_from_archive (&found_archive_locales, &error)) {
-                g_warning ("Failed to load locales from archive: %s", error->message);
-                g_clear_error (&error);
-        }
+        found_localebin_locales = collect_locales_from_localebin ();
 
         found_dir_locales = collect_locales_from_directory ();
 
-        if (!(found_archive_locales || found_dir_locales)) {
-#ifndef WITH_INCOMPLETE_LOCALES
+        if (!(found_localebin_locales || found_dir_locales)) {
                 g_warning ("Could not read list of available locales from libc, "
                            "guessing possible locales from available translations, "
                            "but list may be incomplete!");
-#endif
         }
 
        count_languages_and_territories ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]