mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-03 17:48:56 +01:00 
			
		
		
		
	Clean up g_settings_list_schemas()
In its previous form, g_settings_list_schemas() was not useful as a tool to prevent aborts due to using g_settings_new() with an invalid schema name. This is because g_settings_list_scheams() also listed relocatable schemas, and calling g_settings_new() for those would abort just the same as if you called it for a non-existent schema. Modify g_settings_list_schemas() so that it only returns schemas for which it is safe to call g_settings_new(). Add another call for sake of completeness: g_settings_list_relocatable_schemas().
This commit is contained in:
		@@ -1520,6 +1520,7 @@ g_keyfile_settings_backend_new
 | 
				
			|||||||
#if IN_HEADER(__G_SETTINGS_H__)
 | 
					#if IN_HEADER(__G_SETTINGS_H__)
 | 
				
			||||||
#if IN_FILE(__G_SETTINGS_SCHEMA_C__)
 | 
					#if IN_FILE(__G_SETTINGS_SCHEMA_C__)
 | 
				
			||||||
g_settings_list_schemas
 | 
					g_settings_list_schemas
 | 
				
			||||||
 | 
					g_settings_list_relocatable_schemas
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if IN_FILE(__G_SETTINGS_C__)
 | 
					#if IN_FILE(__G_SETTINGS_C__)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,6 +71,7 @@ struct _GSettings
 | 
				
			|||||||
GType                   g_settings_get_type                             (void);
 | 
					GType                   g_settings_get_type                             (void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const gchar * const *   g_settings_list_schemas                         (void);
 | 
					const gchar * const *   g_settings_list_schemas                         (void);
 | 
				
			||||||
 | 
					const gchar * const *   g_settings_list_relocatable_schemas             (void);
 | 
				
			||||||
GSettings *             g_settings_new                                  (const gchar        *schema);
 | 
					GSettings *             g_settings_new                                  (const gchar        *schema);
 | 
				
			||||||
GSettings *             g_settings_new_with_path                        (const gchar        *schema,
 | 
					GSettings *             g_settings_new_with_path                        (const gchar        *schema,
 | 
				
			||||||
                                                                         const gchar        *path);
 | 
					                                                                         const gchar        *path);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,65 +83,129 @@ initialise_schema_sources (void)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static gboolean
 | 
				
			||||||
add_item (gpointer key,
 | 
					steal_item (gpointer key,
 | 
				
			||||||
          gpointer value,
 | 
					            gpointer value,
 | 
				
			||||||
          gpointer user_data)
 | 
					            gpointer user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  gchar ***ptr = user_data;
 | 
					  gchar ***ptr = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  *(*ptr)++ = (gchar *) key;
 | 
					  *(*ptr)++ = (gchar *) key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					static const gchar * const *non_relocatable_schema_list;
 | 
				
			||||||
 * g_settings_list_schemas:
 | 
					static const gchar * const *relocatable_schema_list;
 | 
				
			||||||
 * @returns: a list of the schemas installed on the system
 | 
					static gsize schema_lists_initialised;
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns: (element-type utf8) (transfer none):  a list of GSettings schemas that are available.  The list
 | 
					 | 
				
			||||||
 * must not be modified or freed.
 | 
					 | 
				
			||||||
 **/
 | 
					 | 
				
			||||||
const gchar * const *
 | 
					 | 
				
			||||||
g_settings_list_schemas (void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  static gsize schema_list;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (g_once_init_enter (&schema_list))
 | 
					static void
 | 
				
			||||||
 | 
					ensure_schema_lists (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (g_once_init_enter (&schema_lists_initialised))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      GHashTable *builder;
 | 
					      GHashTable *single, *reloc;
 | 
				
			||||||
 | 
					      const gchar **ptr;
 | 
				
			||||||
      GSList *source;
 | 
					      GSList *source;
 | 
				
			||||||
      gchar **list;
 | 
					      gchar **list;
 | 
				
			||||||
      gchar **ptr;
 | 
					 | 
				
			||||||
      gint i;
 | 
					      gint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      initialise_schema_sources ();
 | 
					      initialise_schema_sources ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      builder = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 | 
					      /* We use hash tables to avoid duplicate listings for schemas that
 | 
				
			||||||
 | 
					       * appear in more than one file.
 | 
				
			||||||
 | 
					       */
 | 
				
			||||||
 | 
					      single = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 | 
				
			||||||
 | 
					      reloc = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (source = schema_sources; source; source = source->next)
 | 
					      for (source = schema_sources; source; source = source->next)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          list = gvdb_table_list (source->data, "");
 | 
					          list = gvdb_table_list (source->data, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if (list)
 | 
					          g_assert (list != NULL);
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              for (i = 0; list[i]; i++)
 | 
					 | 
				
			||||||
                g_hash_table_insert (builder, list[i], NULL);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              /* not strfreev: we stole the strings into the hashtable */
 | 
					          for (i = 0; list[i]; i++)
 | 
				
			||||||
              g_free (list);
 | 
					            {
 | 
				
			||||||
 | 
					              if (!g_hash_table_lookup (single, list[i]) &&
 | 
				
			||||||
 | 
					                  !g_hash_table_lookup (reloc, list[i]))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                  GvdbTable *table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  table = gvdb_table_get_table (source->data, list[i]);
 | 
				
			||||||
 | 
					                  g_assert (table != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  if (gvdb_table_has_value (table, ".path"))
 | 
				
			||||||
 | 
					                    g_hash_table_insert (single, g_strdup (list[i]), NULL);
 | 
				
			||||||
 | 
					                  else
 | 
				
			||||||
 | 
					                    g_hash_table_insert (reloc, g_strdup (list[i]), NULL);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          g_strfreev (list);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      ptr = list = g_new (gchar *, g_hash_table_size (builder) + 1);
 | 
					      ptr = g_new (const gchar *, g_hash_table_size (single) + 1);
 | 
				
			||||||
      g_hash_table_foreach (builder, add_item, &ptr);
 | 
					      non_relocatable_schema_list = ptr;
 | 
				
			||||||
 | 
					      g_hash_table_foreach_steal (single, steal_item, &ptr);
 | 
				
			||||||
 | 
					      g_hash_table_unref (single);
 | 
				
			||||||
      *ptr = NULL;
 | 
					      *ptr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      g_hash_table_steal_all (builder);
 | 
					      ptr = g_new (const gchar *, g_hash_table_size (reloc) + 1);
 | 
				
			||||||
      g_hash_table_unref (builder);
 | 
					      relocatable_schema_list = ptr;
 | 
				
			||||||
 | 
					      g_hash_table_foreach_steal (reloc, steal_item, &ptr);
 | 
				
			||||||
 | 
					      g_hash_table_unref (reloc);
 | 
				
			||||||
 | 
					      *ptr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      g_once_init_leave (&schema_list, (gsize) list);
 | 
					      g_once_init_leave (&schema_lists_initialised, TRUE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (const gchar **) schema_list;
 | 
					/**
 | 
				
			||||||
 | 
					 * g_settings_list_schemas:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Gets a list of the #GSettings schemas installed on the system.  The
 | 
				
			||||||
 | 
					 * returned list is exactly the list of schemas for which you may call
 | 
				
			||||||
 | 
					 * g_settings_new() without adverse effects.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function does not list the schemas that do not provide their own
 | 
				
			||||||
 | 
					 * paths (ie: schemas for which you must use
 | 
				
			||||||
 | 
					 * g_settings_new_with_path()).  See
 | 
				
			||||||
 | 
					 * g_settings_list_relocatable_schemas() for that.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: (element-type utf8) (transfer none):  a list of #GSettings
 | 
				
			||||||
 | 
					 *   schemas that are available.  The list must not be modified or
 | 
				
			||||||
 | 
					 *   freed.
 | 
				
			||||||
 | 
					 **/
 | 
				
			||||||
 | 
					const gchar * const *
 | 
				
			||||||
 | 
					g_settings_list_schemas (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ensure_schema_lists ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return non_relocatable_schema_list;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * g_settings_list_relocatable_schemas:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Gets a list of the relocatable #GSettings schemas installed on the
 | 
				
			||||||
 | 
					 * system.  These are schemas that do not provide their own path.  It is
 | 
				
			||||||
 | 
					 * usual to instantiate these schemas directly, but if you want to you
 | 
				
			||||||
 | 
					 * can use g_settings_new_with_path() to specify the path.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The output of this function, tTaken together with the output of
 | 
				
			||||||
 | 
					 * g_settings_list_schemas() represents the complete list of all
 | 
				
			||||||
 | 
					 * installed schemas.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: (element-type utf8) (transfer none): a list of relocatable
 | 
				
			||||||
 | 
					 *   #GSettings schemas that are available.  The list must not be
 | 
				
			||||||
 | 
					 *   modified or freed.
 | 
				
			||||||
 | 
					 **/
 | 
				
			||||||
 | 
					const gchar * const *
 | 
				
			||||||
 | 
					g_settings_list_relocatable_schemas (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ensure_schema_lists ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return relocatable_schema_list;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1765,12 +1765,17 @@ static void
 | 
				
			|||||||
test_list_schemas (void)
 | 
					test_list_schemas (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const gchar * const *schemas;
 | 
					  const gchar * const *schemas;
 | 
				
			||||||
 | 
					  const gchar * const *relocs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  relocs = g_settings_list_relocatable_schemas ();
 | 
				
			||||||
  schemas = g_settings_list_schemas ();
 | 
					  schemas = g_settings_list_schemas ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_assert (strv_set_equal ((gchar **)relocs,
 | 
				
			||||||
 | 
					                            "org.gtk.test.no-path",
 | 
				
			||||||
 | 
					                            NULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_assert (strv_set_equal ((gchar **)schemas,
 | 
					  g_assert (strv_set_equal ((gchar **)schemas,
 | 
				
			||||||
                            "org.gtk.test",
 | 
					                            "org.gtk.test",
 | 
				
			||||||
                            "org.gtk.test.no-path",
 | 
					 | 
				
			||||||
                            "org.gtk.test.basic-types",
 | 
					                            "org.gtk.test.basic-types",
 | 
				
			||||||
                            "org.gtk.test.complex-types",
 | 
					                            "org.gtk.test.complex-types",
 | 
				
			||||||
                            "org.gtk.test.localized",
 | 
					                            "org.gtk.test.localized",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user