示例#1
0
static gboolean
mateconf_backend_verify_vtable (MateConfBackendVTable  *vtable,
			     MateConfBackendVTable  *vtable_copy,
			     const char          *backend_name,			    
			     GError             **err)
{
  int i;
  struct
  {
    char  *name;
    gsize  offset;
  } required_vtable_functions[] = {
    { "shutdown",        G_STRUCT_OFFSET(MateConfBackendVTable, shutdown)        },
    { "resolve_address", G_STRUCT_OFFSET(MateConfBackendVTable, resolve_address) },
    { "query_value",     G_STRUCT_OFFSET(MateConfBackendVTable, query_value)     },
    { "query_metainfo",  G_STRUCT_OFFSET(MateConfBackendVTable, query_metainfo)  },
    { "set_value",       G_STRUCT_OFFSET(MateConfBackendVTable, set_value)       },
    { "all_entries",     G_STRUCT_OFFSET(MateConfBackendVTable, all_entries)     },
    { "all_subdirs",     G_STRUCT_OFFSET(MateConfBackendVTable, all_subdirs)     },
    { "unset_value",     G_STRUCT_OFFSET(MateConfBackendVTable, unset_value)     },
    { "dir_exists",      G_STRUCT_OFFSET(MateConfBackendVTable, dir_exists)      },
    { "remove_dir",      G_STRUCT_OFFSET(MateConfBackendVTable, remove_dir)      },
    { "set_schema",      G_STRUCT_OFFSET(MateConfBackendVTable, set_schema)      },
    { "sync_all",        G_STRUCT_OFFSET(MateConfBackendVTable, sync_all)        },
    { "destroy_source",  G_STRUCT_OFFSET(MateConfBackendVTable, destroy_source)  },
    { "blow_away_locks", G_STRUCT_OFFSET(MateConfBackendVTable, blow_away_locks) }
  };

  if (!vtable)
    {
      mateconf_set_error(err,
		      MATECONF_ERROR_FAILED, _("Backend `%s' failed return a vtable\n"),
		      backend_name);
      return FALSE;
    }

  /* Create a copy in case vtable size doesn't match */
  memcpy(vtable_copy, vtable, MIN(vtable->vtable_size, sizeof(MateConfBackendVTable)));

  vtable_copy->vtable_size = sizeof(MateConfBackendVTable);

  for (i = 0; i < G_N_ELEMENTS(required_vtable_functions); i++)
    {
      if (G_STRUCT_MEMBER_P(vtable_copy, required_vtable_functions[i].offset) == NULL)
	{
	  mateconf_set_error(err,
			  MATECONF_ERROR_FAILED, _("Backend `%s' missing required vtable member `%s'\n"),
			  backend_name,
			  required_vtable_functions[i].name);
	  return FALSE;
	}
    }

  return TRUE;
}
示例#2
0
MateConfBackend* 
mateconf_get_backend(const gchar* address, GError** err)
{
  MateConfBackend* backend;
  gchar* name;
  gchar* why_invalid;

  if (loaded_backends == NULL)
    {
      loaded_backends = g_hash_table_new(g_str_hash, g_str_equal);
    }

  why_invalid = NULL;
  if (!mateconf_address_valid (address, &why_invalid))
    {
      g_assert (why_invalid != NULL);
      mateconf_set_error (err, MATECONF_ERROR_BAD_ADDRESS, _("Bad address `%s': %s"),
		       address, why_invalid);
      g_free (why_invalid);
      return NULL;
    }

  name = mateconf_address_backend(address);
      
  if (name == NULL)
    {
      mateconf_set_error(err, MATECONF_ERROR_BAD_ADDRESS, _("Bad address `%s'"), address);
      return NULL;
    }

  backend = g_hash_table_lookup(loaded_backends, name);

  if (backend != NULL)
    {
      /* Returning a "copy" */
      mateconf_backend_ref(backend);
      g_free(name);
      return backend;
    }
  else
    {
      gchar* file;
          
      file = mateconf_backend_file(address);
          
      if (file != NULL)
        {
          GModule* module;
          MateConfBackendVTable* (*get_vtable)(void);

          if (!g_module_supported())
            g_error(_("MateConf won't work without dynamic module support (gmodule)"));
              
          module = g_module_open(file, G_MODULE_BIND_LAZY);
              
          g_free(file);
          
          if (module == NULL)
            {
              mateconf_set_error(err,
                              MATECONF_ERROR_FAILED, _("Error opening module `%s': %s\n"),
                              name, g_module_error());
              g_free(name);
              return NULL;
            }

          if (!g_module_symbol(module, 
                               "mateconf_backend_get_vtable", 
                               (gpointer*)&get_vtable))
            {
              mateconf_set_error(err,
                              MATECONF_ERROR_FAILED, _("Error initializing module `%s': %s\n"),
                              name, g_module_error());
              g_module_close(module);
              g_free(name);
              return NULL;
            }
          
          backend = g_new0(MateConfBackend, 1);

          backend->module = module;

	  if (!mateconf_backend_verify_vtable((*get_vtable)(), &backend->vtable, name, err))
	    {
	      g_module_close(module);
	      g_free(name);
	      g_free(backend);
	      return NULL;
	    }
              
          backend->name = name;

          g_hash_table_insert(loaded_backends, (gchar*)backend->name, backend);
          
          /* Returning a "copy" */
          mateconf_backend_ref(backend);

          return backend;
        }
      else
        {
          mateconf_set_error(err, MATECONF_ERROR_FAILED,
                          _("Couldn't locate backend module for `%s'"), address);
          return NULL;
        }
    }
}
void
mateconf_sources_set_value   (MateConfSources* sources,
                           const gchar* key,
                           const MateConfValue* value,
			   MateConfSources **modified_sources,
                           GError** err)
{
  GList* tmp;

  g_return_if_fail(sources != NULL);
  g_return_if_fail(key != NULL);
  g_return_if_fail((err == NULL) || (*err == NULL));

  if (modified_sources)
    *modified_sources = NULL;
  
  if (!mateconf_key_check(key, err))
    return;
  
  g_assert(*key != '\0');
  
  if (key[1] == '\0')
    {
      mateconf_set_error(err, MATECONF_ERROR_IS_DIR,
                      _("The '/' name can only be a directory, not a key"));
      return;
    }
  
  tmp = sources->sources;

  while (tmp != NULL)
    {
      MateConfSource* src = tmp->data;

      mateconf_log (GCL_DEBUG, "Setting %s in %s",
                 key, src->address);
      
      /* mateconf_source_set_value return value is whether source
       * was writable at key, not whether err was set.
       */
      if (mateconf_source_set_value (src, key, value, err))
        {
          /* source was writable, err may be set */
          mateconf_log (GCL_DEBUG, "%s was writable in %s", key, src->address);
	  if (modified_sources)
	    {
	      *modified_sources = mateconf_sources_new_from_source (src);
	    }
	  return;
        }
      else
        {
          /* check whether the value is set; if it is, then
             we return an error since setting an overridden value
             would have no effect
          */
          MateConfValue* val;

          val = mateconf_source_query_value(tmp->data, key, NULL, NULL, NULL);
          
          if (val != NULL)
            {
              mateconf_log (GCL_DEBUG, "%s was already set in %s", key, src->address);
              
              mateconf_value_free(val);
              mateconf_set_error(err, MATECONF_ERROR_OVERRIDDEN,
                              _("Value for `%s' set in a read-only source at the front of your configuration path"), key);
              return;
            }
        }

      tmp = g_list_next(tmp);
    }

  /* If we arrived here, then there was nowhere to write a value */
  g_set_error (err,
               MATECONF_ERROR,
               MATECONF_ERROR_NO_WRITABLE_DATABASE,
               _("Unable to store a value at key '%s', as the configuration server has no writable databases. There are some common causes of this problem: 1) your configuration path file %s/path doesn't contain any databases or wasn't found 2) somehow we mistakenly created two mateconfd processes 3) your operating system is misconfigured so NFS file locking doesn't work in your home directory or 4) your NFS client machine crashed and didn't properly notify the server on reboot that file locks should be dropped. If you have two mateconfd processes (or had two at the time the second was launched), logging out, killing all copies of mateconfd, and logging back in may help. If you have stale locks, remove ~/.mateconf*/*lock. Perhaps the problem is that you attempted to use MateConf from two machines at once, and MateCORBA still has its default configuration that prevents remote CORBA connections - put \"ORBIIOPIPv4=1\" in /etc/matecorbarc. As always, check the user.* syslog for details on problems mateconfd encountered. There can only be one mateconfd per home directory, and it must own a lockfile in ~/.mateconfd and also lockfiles in individual storage locations such as ~/.mateconf"),           
               key, MATECONF_CONFDIR);
}
MateConfValue*   
mateconf_sources_query_value (MateConfSources* sources, 
                           const gchar* key,
                           const gchar** locales,
                           gboolean use_schema_default,
                           gboolean* value_is_default,
                           gboolean* value_is_writable,
                           gchar   **schema_namep,
                           GError** err)
{
  GList* tmp;
  gchar* schema_name;
  GError* error;
  MateConfValue* val;
  
  g_return_val_if_fail (sources != NULL, NULL);
  g_return_val_if_fail (key != NULL, NULL);
  g_return_val_if_fail ((err == NULL) || (*err == NULL), NULL);

  /* A value is writable if it is unset and a writable source exists,
   * or if it's set and the setting is within or after a writable source.
   * So basically if we see a writable source before we get the value,
   * or get the value from a writable source, the value is writable.
   */
  
  if (!mateconf_key_check(key, err))
    return NULL;

  if (value_is_default)
    *value_is_default = FALSE;

  if (value_is_writable)
    *value_is_writable = FALSE;

  if (schema_namep)
    *schema_namep = NULL;

  val = NULL;
  schema_name = NULL;
  error = NULL;
  
  tmp = sources->sources;

  while (tmp != NULL)
    {
      MateConfSource* source;      
      gchar** schema_name_retloc;

      schema_name_retloc = &schema_name;
      if (schema_name != NULL ||                          /* already have the schema name */
          (schema_namep == NULL && !use_schema_default))  /* don't need to get the schema name */
        schema_name_retloc = NULL;
      
      source = tmp->data;

      if (val == NULL)
        {
          /* A key is writable if the source containing its value or
           * an earlier source is writable
           */          
          if (value_is_writable &&
              source_is_writable (source, key, NULL)) /* ignore errors */
            *value_is_writable = TRUE;
          
          val = mateconf_source_query_value (source, key, locales,
                                          schema_name_retloc, &error);

        }
      else if (schema_name_retloc != NULL)
        {
          MateConfMetaInfo *mi;
          
          mi = mateconf_source_query_metainfo (source, key, &error);
          
          if (mi)
            {
              *schema_name_retloc = mi->schema;
              mi->schema = NULL;
              mateconf_meta_info_free (mi);
            }
        }
          
      if (error != NULL)
        {
          if (err)
            *err = error;
          else
            g_error_free (error);

          error = NULL;

          if (val)
            mateconf_value_free (val);

          g_free (schema_name);
          
          return NULL;
        }

      /* schema_name_retloc == NULL means we aren't still looking for schema name,
       * tmp->next == NULL means we aren't going to get a schema name
       */
      if (val != NULL && (schema_name_retloc == NULL || schema_name != NULL || tmp->next == NULL))
        {
          if (schema_namep)
            *schema_namep = schema_name;
          else
            g_free (schema_name);
          
          return val;
        }
      else
        {
          ; /* Keep looking for either val or schema name */
        }
      
      tmp = g_list_next (tmp);
    }

  g_return_val_if_fail (error == NULL, NULL);
  g_return_val_if_fail (val == NULL, NULL);
  
  /* If we got here, there was no value; we try to look up the
   * schema for this key if we have one, and use the default
   * value.
   */
  
  if (schema_name != NULL)
    {
      /* Note that if the value isn't found, then it's always the
       * default value - even if there is no default value, NULL is
       * the default.  This makes things more sane (I think) because
       * is_default basically means "was set by user" - however we
       * also want to say that if use_schema_default is FALSE then
       * value_is_default will be FALSE so we put this inside the
       * schema_name != NULL conditional
      */
      if (value_is_default)
        *value_is_default = TRUE;

      if (use_schema_default)
        {
          val = mateconf_sources_query_value (sources, schema_name, locales,
                                           FALSE, NULL, NULL, NULL, &error);
        }
      
      if (error != NULL)
        {
          if (err)
            *err = error;
          else
            g_error_free(error);

          g_free(schema_name);
          return NULL;
        }
      else if (val != NULL &&
               val->type != MATECONF_VALUE_SCHEMA)
        {
          mateconf_set_error (err, MATECONF_ERROR_FAILED,
                           _("Schema `%s' specified for `%s' stores a non-schema value"), schema_name, key);

          if (schema_namep)
            *schema_namep = schema_name;
          else
            g_free (schema_name);

          return NULL;
        }
      else if (val != NULL)
        {
          MateConfValue* retval;

          retval = mateconf_schema_steal_default_value (mateconf_value_get_schema (val));          

          mateconf_value_free (val);

          if (schema_namep)
            *schema_namep = schema_name;
          else
            g_free (schema_name);
          
          return retval;
        }
      else
        {
          if (schema_namep)
            *schema_namep = schema_name;
          else
            g_free (schema_name);
          
          return NULL;
        }
    }
  
  return NULL;
}