GVariant *
mm_bearer_properties_get_dictionary (MMBearerProperties *self)
{
    GVariantBuilder builder;

    /* We do allow NULL */
    if (!self)
        return NULL;

    g_return_val_if_fail (MM_IS_BEARER_PROPERTIES (self), NULL);

    g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

    if (self->priv->apn)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_APN,
                               g_variant_new_string (self->priv->apn));

    if (self->priv->allowed_auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_ALLOWED_AUTH,
                               g_variant_new_uint32 (self->priv->allowed_auth));

    if (self->priv->user)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_USER,
                               g_variant_new_string (self->priv->user));

    if (self->priv->password)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_PASSWORD,
                               g_variant_new_string (self->priv->password));

    if (self->priv->ip_type != MM_BEARER_IP_FAMILY_UNKNOWN)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_IP_TYPE,
                               g_variant_new_uint32 (self->priv->ip_type));

    if (self->priv->number)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_NUMBER,
                               g_variant_new_string (self->priv->number));

    if (self->priv->allow_roaming_set)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_ALLOW_ROAMING,
                               g_variant_new_boolean (self->priv->allow_roaming));

    if (self->priv->rm_protocol)
        g_variant_builder_add (&builder,
                               "{sv}",
                               PROPERTY_RM_PROTOCOL,
                               g_variant_new_uint32 (self->priv->rm_protocol));

    return g_variant_ref_sink (g_variant_builder_end (&builder));
}
示例#2
0
static void CACentralStartDiscoveryImpl(gpointer proxy, gpointer user_data)
{
    assert(proxy != NULL);
    assert(user_data != NULL);

    GDBusProxy * const adapter = G_DBUS_PROXY(proxy);
    CAResult_t * const result  = user_data;

    *result = CA_STATUS_FAILED;

    bool const is_discovering =
        CACentralGetBooleanProperty(adapter, "Discovering");

    if (is_discovering)
    {
        // Nothing to do.  Avoid invoking a method over D-Bus.
        *result = CA_STATUS_OK;
        return;
    }


    // Make sure the adapter is powered on before starting discovery.
    if (!CASetBlueZObjectProperty(adapter,
                                  BLUEZ_ADAPTER_INTERFACE,
                                  "Powered",
                                  g_variant_new_boolean(TRUE)))
    {
        OIC_LOG(ERROR,
                TAG,
                "Unable to power on LE central adapter.");

        return;
    }

    /*
      Only scan for LE peripherals that advertise the OIC Transport
      Profile GATT service UUID by setting a discovery filter on the BlueZ
      org.bluez.Adapter1 object with two parameters:

          (1) "UUIDs": set to an array containing that OIC Transport
                       Profile GATT service UUID
          (2) "Transport": set to "le"

      See the documentation for the SetDiscoveryFilter() method in the
      BlueZ `adapter-api.txt' document for more details.
    */
    GVariantBuilder builder;
    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));

    static char const * const UUIDs[] =
        {
            CA_GATT_SERVICE_UUID
        };

    g_variant_builder_add(&builder,
                          "{sv}",
                          "UUIDs",
                          g_variant_new_strv(
                              UUIDs,
                              sizeof(UUIDs) / sizeof(UUIDs[0])));

    g_variant_builder_add(&builder,
                          "{sv}",
                          "Transport",
                          g_variant_new_string("le"));

    GVariant * const filter = g_variant_builder_end(&builder);

    /*
      SetDiscoveryFilter() expects a dictionary but it must be packed
      into a tuple for the actual call through the proxy.
    */
    GVariant * const filter_parameters =
        g_variant_new("(@a{sv})", filter);

    GError * error = NULL;

    /*
      This is a synchronous call, but the actually discovery is
      performed asynchronously.  org.bluez.Device1 objects will
      reported through the
      org.freedesktop.DBus.ObjectManager.InterfacesAdded signal as
      peripherals that match our discovery filter criteria are found.
     */
    GVariant * ret =
        g_dbus_proxy_call_sync(adapter,
                               "SetDiscoveryFilter",
                               filter_parameters,
                               G_DBUS_CALL_FLAGS_NONE,
                               -1,    // timeout (default == -1),
                               NULL,  // cancellable
                               &error);

    if (ret == NULL)
    {
        OIC_LOG_V(ERROR,
                  TAG,
                  "SetDiscoveryFilter() call failed: %s",
                  error->message);

        g_error_free(error);

        return;
    }

    g_variant_unref(ret);

    // Start device discovery.
    ret = g_dbus_proxy_call_sync(adapter,
                                 "StartDiscovery",
                                 NULL,  // parameters
                                 G_DBUS_CALL_FLAGS_NONE,
                                 -1,    // timeout (default == -1),
                                 NULL,  // cancellable
                                 &error);

    if (ret == NULL)
    {
        OIC_LOG_V(ERROR,
                  TAG,
                  "StartDiscovery() call failed: %s",
                  error->message);

        g_error_free(error);

        return;
    }

    g_variant_unref(ret);

    *result = CA_STATUS_OK;
}
static gboolean
rewrite_delta (OstreeRepo *src_repo,
               const char *src_commit,
               OstreeRepo *dst_repo,
               const char *dst_commit,
               GVariant   *dst_commitv,
               const char *from,
               GError    **error)
{
  g_autoptr(GFile) src_delta_file = NULL;
  g_autoptr(GFile) dst_delta_file = NULL;
  g_autofree char *src_detached_key = _ostree_get_relative_static_delta_path (from, src_commit, "commitmeta");
  g_autofree char *dst_detached_key = _ostree_get_relative_static_delta_path (from, dst_commit, "commitmeta");
  g_autofree char *src_delta_dir = _ostree_get_relative_static_delta_path (from, src_commit, NULL);
  g_autofree char *dst_delta_dir = _ostree_get_relative_static_delta_path (from, dst_commit, NULL);
  g_autofree char *src_superblock_path = _ostree_get_relative_static_delta_path (from, src_commit, "superblock");
  g_autofree char *dst_superblock_path = _ostree_get_relative_static_delta_path (from, dst_commit, "superblock");
  GMappedFile *mfile = NULL;
  g_auto(GVariantBuilder) superblock_builder = FLATPAK_VARIANT_BUILDER_INITIALIZER;
  g_autoptr(GVariant) src_superblock = NULL;
  g_autoptr(GVariant) dst_superblock = NULL;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GVariant) dst_detached = NULL;
  g_autoptr(GVariant) src_metadata = NULL;
  g_autoptr(GVariant) src_recurse = NULL;
  g_autoptr(GVariant) src_parts = NULL;
  g_auto(GVariantDict) dst_metadata_dict = FLATPAK_VARIANT_DICT_INITIALIZER;
  int i;

  src_delta_file = g_file_resolve_relative_path (ostree_repo_get_path (src_repo), src_superblock_path);
  mfile = g_mapped_file_new (flatpak_file_get_path_cached (src_delta_file), FALSE, NULL);
  if (mfile == NULL)
    return TRUE; /* No superblock, not an error */

  bytes = g_mapped_file_get_bytes (mfile);
  g_mapped_file_unref (mfile);

  src_superblock = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), bytes, FALSE));

  src_metadata = g_variant_get_child_value (src_superblock, 0);
  src_recurse = g_variant_get_child_value (src_superblock, 5);
  src_parts = g_variant_get_child_value (src_superblock, 6);

  if (g_variant_n_children (src_recurse) != 0)
    return flatpak_fail (error, "Recursive deltas not supported, ignoring");

  g_variant_builder_init (&superblock_builder, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT));

  g_variant_dict_init (&dst_metadata_dict, src_metadata);
  g_variant_dict_remove (&dst_metadata_dict, src_detached_key);
  if (ostree_repo_read_commit_detached_metadata (dst_repo, dst_commit, &dst_detached, NULL, NULL) &&
      dst_detached != NULL)
    g_variant_dict_insert_value (&dst_metadata_dict, dst_detached_key, dst_detached);

  g_variant_builder_add_value (&superblock_builder, g_variant_dict_end (&dst_metadata_dict));
  g_variant_builder_add_value (&superblock_builder, g_variant_get_child_value (src_superblock, 1)); /* timestamp */
  g_variant_builder_add_value (&superblock_builder, from ? ostree_checksum_to_bytes_v (from) : new_bytearray ((guchar *) "", 0));
  g_variant_builder_add_value (&superblock_builder, ostree_checksum_to_bytes_v (dst_commit));
  g_variant_builder_add_value (&superblock_builder, dst_commitv);
  g_variant_builder_add_value (&superblock_builder, src_recurse);
  g_variant_builder_add_value (&superblock_builder, src_parts);
  g_variant_builder_add_value (&superblock_builder, g_variant_get_child_value (src_superblock, 7)); /* fallback */

  dst_superblock = g_variant_ref_sink (g_variant_builder_end (&superblock_builder));

  if (!glnx_shutil_mkdir_p_at (ostree_repo_get_dfd (dst_repo), dst_delta_dir, 0755, NULL, error))
    return FALSE;

  for (i = 0; i < g_variant_n_children (src_parts); i++)
    {
      g_autofree char *src_part_path = g_strdup_printf ("%s/%d", src_delta_dir, i);
      g_autofree char *dst_part_path = g_strdup_printf ("%s/%d", dst_delta_dir, i);

      if (!glnx_file_copy_at (ostree_repo_get_dfd (src_repo),
                              src_part_path,
                              NULL,
                              ostree_repo_get_dfd (dst_repo),
                              dst_part_path,
                              GLNX_FILE_COPY_OVERWRITE | GLNX_FILE_COPY_NOXATTRS,
                              NULL, error))
        return FALSE;
    }

  dst_delta_file = g_file_resolve_relative_path (ostree_repo_get_path (dst_repo), dst_superblock_path);
  if (!flatpak_variant_save (dst_delta_file, dst_superblock, NULL, error))
    return FALSE;

  return TRUE;
}
示例#4
0
static GHashTable *
parse_resource_file (const gchar *filename,
                     gboolean     collect_data,
                     GHashTable  *files)
{
  GMarkupParser parser = { start_element, end_element, text };
  ParseState state = { 0, };
  GMarkupParseContext *context;
  GError *error = NULL;
  gchar *contents;
  GHashTable *table = NULL;
  gsize size;

  if (!g_file_get_contents (filename, &contents, &size, &error))
    {
      g_printerr ("%s\n", error->message);
      g_clear_error (&error);
      return NULL;
    }

  state.collect_data = collect_data;
  state.table = g_hash_table_ref (files);

  context = g_markup_parse_context_new (&parser,
					G_MARKUP_TREAT_CDATA_AS_TEXT |
					G_MARKUP_PREFIX_ERROR_POSITION,
					&state, NULL);

  if (!g_markup_parse_context_parse (context, contents, size, &error) ||
      !g_markup_parse_context_end_parse (context, &error))
    {
      g_printerr ("%s: %s.\n", filename, error->message);
      g_clear_error (&error);
    }
  else
    {
      GHashTableIter iter;
      const char *key;
      char *mykey;
      gsize key_len;
      FileData *data;
      GVariant *v_data;
      GVariantBuilder builder;
      GvdbItem *item;

      table = gvdb_hash_table_new (NULL, NULL);

      g_hash_table_iter_init (&iter, state.table);
      while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&data))
	{
	  key_len = strlen (key);
	  mykey = g_strdup (key);

	  item = gvdb_hash_table_insert (table, key);
	  gvdb_item_set_parent (item,
				get_parent (table, mykey, key_len));

	  g_free (mykey);

	  g_variant_builder_init (&builder, G_VARIANT_TYPE ("(uuay)"));

	  g_variant_builder_add (&builder, "u", data->size); /* Size */
	  g_variant_builder_add (&builder, "u", data->flags); /* Flags */

	  v_data = g_variant_new_from_data (G_VARIANT_TYPE("ay"),
					    data->content, data->content_size, TRUE,
					    g_free, data->content);
	  g_variant_builder_add_value (&builder, v_data);
	  data->content = NULL; /* Take ownership */

	  gvdb_item_set_value (item,
			       g_variant_builder_end (&builder));
	}
    }

  g_hash_table_unref (state.table);
  g_markup_parse_context_free (context);
  g_free (contents);

  return table;
}
gboolean
gkd_secret_objects_handle_search_items (GkdSecretObjects *self,
					GDBusMethodInvocation *invocation,
					GVariant *attributes,
					const gchar *base,
					gboolean separate_locked)
{
	GckBuilder builder = GCK_BUILDER_INIT;
	GckObject *search;
	GckSession *session;
	GError *error = NULL;
	gchar *identifier;
	gpointer data;
	gsize n_data;
	GList *locked, *unlocked;
	GList *items;
	GVariantBuilder result;

	if (!gkd_secret_property_parse_fields (attributes, &builder)) {
		gck_builder_clear (&builder);
		g_dbus_method_invocation_return_error_literal (invocation,
							       G_DBUS_ERROR,
							       G_DBUS_ERROR_FAILED,
							       "Invalid data in attributes argument");
		return TRUE;
	}

	if (base != NULL) {
		if (!parse_object_path (self, base, &identifier, NULL))
			g_return_val_if_reached (FALSE);
		gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
		g_free (identifier);
	}

	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
	gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);

	/* The session we're using to access the object */
	session = gkd_secret_service_get_pkcs11_session (self->service, g_dbus_method_invocation_get_sender (invocation));
	g_return_val_if_fail (session, FALSE);

	/* Create the search object */
	search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);

	if (error != NULL) {
		g_dbus_method_invocation_return_error (invocation,
						       G_DBUS_ERROR,
						       G_DBUS_ERROR_FAILED,
						       "Couldn't search for items: %s",
						       egg_error_message (error));
		g_clear_error (&error);
		return TRUE;
	}

	/* Get the matched item handles, and delete the search object */
	data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, &error);
	gck_object_destroy (search, NULL, NULL);
	g_object_unref (search);

	if (error != NULL) {
		g_dbus_method_invocation_return_error (invocation,
						       G_DBUS_ERROR,
						       G_DBUS_ERROR_FAILED,
						       "Couldn't retrieve matched items: %s",
						       egg_error_message (error));
		g_clear_error (&error);
		return TRUE;
	}

	/* Build a list of object handles */
	items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE));
	g_free (data);

	/* Filter out the locked items */
	if (separate_locked) {
		GVariant *unlocked_variant, *locked_variant;

		item_cleanup_search_results (session, items, &locked, &unlocked);

		g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
		objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_builder, &result);
		unlocked_variant = g_variant_builder_end (&result);

		g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
		objects_foreach_item (self, locked, NULL, on_object_path_append_to_builder, &result);
		locked_variant = g_variant_builder_end (&result);

		g_list_free (locked);
		g_list_free (unlocked);

		g_dbus_method_invocation_return_value (invocation,
						       g_variant_new ("(@ao@ao)",
								      unlocked_variant,
								      locked_variant));
	} else {
		g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
		objects_foreach_item (self, items, NULL, on_object_path_append_to_builder, &result);

		g_dbus_method_invocation_return_value (invocation,
						       g_variant_new ("(@ao)", g_variant_builder_end (&result)));
	}

	gck_list_unref_free (items);

	return TRUE;
}
示例#6
0
文件: fwupd-result.c 项目: swem/fwupd
/**
 * fwupd_result_to_data:
 * @result: A #FwupdResult
 * @type_string: The Gvariant type string, e.g. "{sa{sv}}" or "(a{sv})"
 *
 * Creates a GVariant from the result data.
 *
 * Returns: the GVariant, or %NULL for error
 *
 * Since: 0.7.0
 **/
GVariant *
fwupd_result_to_data (FwupdResult *result, const gchar *type_string)
{
	FwupdResultPrivate *priv = GET_PRIVATE (result);
	GVariantBuilder builder;

	g_return_val_if_fail (FWUPD_IS_RESULT (result), NULL);
	g_return_val_if_fail (type_string != NULL, NULL);

	/* create an array with all the metadata in */
	g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
	if (priv->guid != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_GUID,
				       g_variant_new_string (priv->guid));
	}
	if (priv->device_name != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_NAME,
				       g_variant_new_string (priv->device_name));
	}
	if (priv->device_vendor != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_VENDOR,
				       g_variant_new_string (priv->device_vendor));
	}
	if (priv->device_flags > 0) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_FLAGS,
				       g_variant_new_uint64 (priv->device_flags));
	}
	if (priv->device_created > 0) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_CREATED,
				       g_variant_new_uint64 (priv->device_created));
	}
	if (priv->device_modified > 0) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_MODIFIED,
				       g_variant_new_uint64 (priv->device_modified));
	}

	if (priv->update_id != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_ID,
				       g_variant_new_string (priv->update_id));
	}
	if (priv->device_description != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_DESCRIPTION,
				       g_variant_new_string (priv->device_description));
	}
	if (priv->update_filename != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_FILENAME,
				       g_variant_new_string (priv->update_filename));
	}
	if (priv->device_checksum != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_CHECKSUM,
				       g_variant_new_string (priv->device_checksum));
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_CHECKSUM_KIND,
				       g_variant_new_uint32 (priv->device_checksum_kind));
	}
	if (priv->update_license != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_LICENSE,
				       g_variant_new_string (priv->update_license));
	}
	if (priv->update_name != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_NAME,
				       g_variant_new_string (priv->update_name));
	}
	if (priv->update_error != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_ERROR,
				       g_variant_new_string (priv->update_error));
	}
	if (priv->update_state != FWUPD_UPDATE_STATE_UNKNOWN) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_STATE,
				       g_variant_new_uint32 (priv->update_state));
	}
	if (priv->device_provider != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_PROVIDER,
				       g_variant_new_string (priv->device_provider));
	}
	if (priv->update_size != 0) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_SIZE,
				       g_variant_new_uint64 (priv->update_size));
	}
	if (priv->update_trust_flags != 0) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_TRUST_FLAGS,
				       g_variant_new_uint64 (priv->update_trust_flags));
	}
	if (priv->update_summary != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_SUMMARY,
				       g_variant_new_string (priv->update_summary));
	}
	if (priv->update_description != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_DESCRIPTION,
				       g_variant_new_string (priv->update_description));
	}
	if (priv->update_checksum != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_CHECKSUM,
				       g_variant_new_string (priv->update_checksum));
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_CHECKSUM_KIND,
				       g_variant_new_uint32 (priv->update_checksum_kind));
	}
	if (priv->update_uri != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_URI,
				       g_variant_new_string (priv->update_uri));
	}
	if (priv->update_homepage != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_HOMEPAGE,
				       g_variant_new_string (priv->update_homepage));
	}
	if (priv->update_version != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_VERSION,
				       g_variant_new_string (priv->update_version));
	}
	if (priv->update_vendor != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_UPDATE_VENDOR,
				       g_variant_new_string (priv->update_vendor));
	}
	if (priv->device_version != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_VERSION,
				       g_variant_new_string (priv->device_version));
	}
	if (priv->device_version_lowest != NULL) {
		g_variant_builder_add (&builder, "{sv}",
				       FWUPD_RESULT_KEY_DEVICE_VERSION_LOWEST,
				       g_variant_new_string (priv->device_version_lowest));
	}

	/* supported types */
	if (g_strcmp0 (type_string, "{sa{sv}}") == 0)
		return g_variant_new ("{sa{sv}}", priv->device_id, &builder);
	if (g_strcmp0 (type_string, "(a{sv})") == 0)
		return g_variant_new ("(a{sv})", &builder);
	return NULL;
}
static void handleMethodCall(GDBusConnection       *connection,
							 const gchar           *sender,
							 const gchar           *object_path,
							 const gchar           *interface_name,
							 const gchar           *method_name,
							 GVariant              *parameters,
							 GDBusMethodInvocation *invocation,
							 gpointer               user_data)
{

	AutomotiveManager* manager = static_cast<AutomotiveManager*>(user_data);

	std::string method = method_name;

	uint pid = getPid(sender);

	if(DebugOut::getDebugThreshhold() >= 6)
	{
		DebugOut(6)<<"DBus method call from: "<<sender<< " pid: " <<pid<< " interface: "<<interface_name<<" method: "<<method<<endl;
		DebugOut(6)<<"DBus method call path: "<<object_path<<endl;
	}

	if(method == "FindObject")
	{
		gchar* arg;

		g_variant_get(parameters,"(s)",&arg);

		std::string objectToFind = arg;

		if(objectToFind == "")
		{
			g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
			return;
		}

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectToFind);

		if(!interfaces.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Object not found");
			return;
		}

		GVariantBuilder params;
		g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);

		bool hasItems = false;

		for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
		{
			AbstractDBusInterface* t = *itr;
			if(!t->isSupported())
				continue;

			hasItems = true;

			if(!t->isRegistered())
				t->registerObject();

			std::list<std::string> processes = manager->subscribedProcesses[t];

			if(!contains(processes,sender))
			{
				DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
				manager->subscribedProcesses[t].push_back(sender);
			}

			GVariant *newvar = g_variant_new("o",t->objectPath().c_str());
			g_variant_builder_add_value(&params, newvar);
		}

		if(hasItems)
			g_dbus_method_invocation_return_value(invocation, g_variant_new("(ao)",&params));
		else
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");

	}

	else if(method == "FindObjectForZone")
	{
		gchar* arg;
		int zone;

		g_variant_get(parameters,"(si)", &arg, &zone);

		std::string propertyToFind = arg;

		if(propertyToFind == "")
		{
			g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
			return;
		}

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);

		if(!interfaces.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation, "org.automotive.Manager.ObjectNotFound", "Property not found");
			return;
		}



		for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
		{
			AbstractDBusInterface* t = *itr;

			if(t->zone() == (Zone::Type)zone)
			{
				if(!t->isRegistered())
					t->registerObject();

				std::list<std::string> processes = manager->subscribedProcesses[t];

				if(!contains(processes,sender))
				{
					DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
					manager->subscribedProcesses[t].push_back(sender);
				}

				g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
				return;
			}
		}

		g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.InvalidZone", "zone not found");
	}

	else if (method == "ZonesForObjectName")
	{
		gchar* arg;

		g_variant_get(parameters,"(s)",&arg);

		std::string propertyToFind = arg;

		if(propertyToFind == "")
		{
			g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
			return;
		}

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);

		if(!interfaces.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
			return;
		}

		GVariantBuilder params;
		g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);

		for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
		{
			AbstractDBusInterface* t = *itr;
			GVariant *newvar = g_variant_new("i",t->zone());
			g_variant_builder_add_value(&params, newvar);

		}

		g_dbus_method_invocation_return_value(invocation,g_variant_new("(ai)",&params));
	}

	else if(method == "List")
	{
		std::list<AbstractDBusInterface*> list = AbstractDBusInterface::interfaces();

		if(!list.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.Error", "No supported objects");
			return;
		}

		GVariantBuilder builder;
		g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);


		for(auto itr = list.begin(); itr != list.end(); itr++)
		{
			if(!(*itr)->isSupported())
				continue;

			std::string objectName = (*itr)->objectName();

			g_variant_builder_add(&builder, "s", objectName.c_str());
		}


		g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&builder));
	}
	else if(method == "SourcesForObjectName")
	{
		gchar* arg;

		g_variant_get(parameters,"(s)",&arg);

		std::string propertyToFind = arg;

		if(propertyToFind == "")
		{
			g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
			return;
		}

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);

		if(!interfaces.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
			return;
		}

		GVariantBuilder params;
		g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);

		for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
		{
			AbstractDBusInterface* t = *itr;
			string source = t->source();
			boost::algorithm::erase_all(source, "-");
			GVariant *newvar = g_variant_new("s", source.c_str());
			g_variant_builder_add_value(&params, newvar);

		}

		g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&params));
	}
	else if(method == "FindObjectForSourceZone")
	{
		gchar* arg;
		gchar* arg2;
		int zone;

		g_variant_get(parameters,"(ssi)", &arg, &arg2, &zone);

		std::string propertyToFind = arg;
		std::string source = arg2;

		if(propertyToFind == "" || source == "")
		{
			g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
			return;
		}

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);

		if(!interfaces.size())
		{
			g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
			return;
		}

		for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
		{
			AbstractDBusInterface* t = *itr;
			string targetSource = t->source();
			boost::algorithm::erase_all(targetSource, "-");
			if(t->zone() == (Zone::Type)zone && source == targetSource)
			{
				if(!t->isRegistered())
					t->registerObject();

				std::list<std::string> processes = manager->subscribedProcesses[t];

				if(!contains(processes,sender))
				{
					DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
					manager->subscribedProcesses[t].push_back(sender);
				}

				g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
				return;
			}
		}

		g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
	}
	else if(method == "SupportsProperty")
	{
		gchar* objectName;
		gchar* propertyToFindStr;

		g_variant_get(parameters,"(ss)",&objectName, &propertyToFindStr);

		auto objectNamePtr = amb::make_super(objectName);
		auto propertyToFindStrPtr = amb::make_super(propertyToFindStr);

		DebugOut(6) << "Checking " << objectNamePtr.get() << " for member: " << propertyToFindStrPtr.get() << endl;

		std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectNamePtr.get());

		for(auto i : interfaces)
		{
			if(i->hasPropertyDBus(propertyToFindStrPtr.get()))
			{
				DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was found!!" << endl;
				g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", true));
				return;
			}
		}
		DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was not found." << endl;
		g_dbus_method_invocation_return_value(invocation,g_variant_new("(b)", false));
	}
	else
	{
		g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
	}
}
示例#8
0
static int config_list(uint32_t key, GVariant **data,
	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
{

	struct dev_context *devc;
	GVariant *gvar;
	GVariantBuilder gvb;
	double dval;
	int idx;

	(void)cg;

	/* Always available (with or without sdi). */
	if (key == SR_CONF_SCAN_OPTIONS) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
			scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
		return SR_OK;
	}

	/* Return drvopts without sdi (and devopts with sdi, see below). */
	if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
			drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
		return SR_OK;
	}

	/* Every other key needs an sdi. */
	if (!sdi)
		return SR_ERR_ARG;

	devc = sdi->priv;

	switch (key) {
	case SR_CONF_DEVICE_OPTIONS:
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
			devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
		break;
	case SR_CONF_VOLTAGE_TARGET:
		g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
		/* Min, max, step. */
		for (idx = 0; idx < 3; idx++) {
			dval = devc->model->voltage[idx];
			gvar = g_variant_new_double(dval);
			g_variant_builder_add_value(&gvb, gvar);
		}
		*data = g_variant_builder_end(&gvb);
		break;
	case SR_CONF_CURRENT_LIMIT:
		g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
		/* Min, max, step. */
		for (idx = 0; idx < 3; idx++) {
			dval = devc->model->current[idx];
			gvar = g_variant_new_double(dval);
			g_variant_builder_add_value(&gvb, gvar);
		}
		*data = g_variant_builder_end(&gvb);
		break;
	default:
		return SR_ERR_NA;
	}

	return SR_OK;
}
示例#9
0
static gboolean
try_existing_instance (GDBusConnection *bus,
                       const char *type,
                       gboolean create,
                       gboolean show,
                       const char *uuid,
                       const char *import)
{
	gs_free char *owner = NULL;
	gs_free_error GError *error = NULL;
	gs_unref_variant GVariant *reply = NULL;
	GVariantBuilder builder;

	g_assert (bus);

	reply = g_dbus_connection_call_sync (bus,
	                                     "org.freedesktop.DBus",
	                                     "/org/freedesktop/DBus",
	                                     "org.freedesktop.DBus",
	                                     "GetNameOwner",
	                                     g_variant_new ("(s)", NM_CE_DBUS_SERVICE),
	                                     G_VARIANT_TYPE ("(s)"),
	                                     G_DBUS_CALL_FLAGS_NONE,
	                                     -1,           /* timeout */
	                                     NULL,
	                                     &error);
	if (!reply) {
		if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
			g_warning ("Failed to get editor name owner: %s", error->message);
		return FALSE;
	}

	g_variant_get (reply, "(s)", &owner);
	if (!owner)
		return FALSE;

	g_variant_unref (reply);

	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
	if (type)
		g_variant_builder_add (&builder, "{sv}", ARG_TYPE, g_variant_new_string (type));
	if (create)
		g_variant_builder_add (&builder, "{sv}", ARG_CREATE, g_variant_new_boolean (TRUE));
	if (show)
		g_variant_builder_add (&builder, "{sv}", ARG_SHOW, g_variant_new_boolean (TRUE));
	if (uuid)
		g_variant_builder_add (&builder, "{sv}", ARG_UUID, g_variant_new_string (uuid));
	if (import)
		g_variant_builder_add (&builder, "{sv}", ARG_IMPORT, g_variant_new_string (import));

	reply = g_dbus_connection_call_sync (bus,
	                                     NM_CE_DBUS_SERVICE,
	                                     "/",
	                                     NM_CE_DBUS_INTERFACE,
	                                     "Start",
	                                     g_variant_new ("(@a{sv})", g_variant_builder_end (&builder)),
	                                     NULL,
	                                     G_DBUS_CALL_FLAGS_NONE,
	                                     -1,           /* timeout */
	                                     NULL,
	                                     &error);
	if (!reply) {
		g_warning ("Failed to send arguments to existing editor instance: %s", error->message);
		return FALSE;
	}

	return TRUE;
}
示例#10
0
/* TODO: this should be optimized so we don't allocate network and call open()/close() all the time */
static void
collect (DiskIOMonitor *monitor)
{
    gchar *contents = NULL;
    gsize len;
    GError *error;
    gchar **lines = NULL;
    guint n;
    gint64 now;
    Sample *sample = NULL;
    Sample *last = NULL;
    GVariantBuilder builder;

    error = NULL;
    if (!g_file_get_contents ("/proc/diskstats",
                              &contents,
                              &len,
                              &error))
    {
        g_warning ("Error loading contents /proc/vmstat: %s (%s, %d)",
                   error->message, g_quark_to_string (error->domain), error->code);
        g_error_free (error);
        goto out;
    }

    now = g_get_real_time ();

    sample = &(monitor->samples[monitor->samples_next]);
    sample->timestamp = now;
    sample->bytes_read = 0;
    sample->bytes_written = 0;
    sample->num_ops = 0;

    if (monitor->samples_prev != -1)
        last = &(monitor->samples[monitor->samples_prev]);

    lines = g_strsplit (contents, "\n", -1);
    for (n = 0; lines != NULL && lines[n] != NULL; n++)
    {
        const gchar *line = lines[n];
        guint num_parsed;
        gint dev_major, dev_minor;
        gchar dev_name[64]; /* TODO: big enough? */
        guint64 num_reads,  num_reads_merged,  num_sectors_read,    num_msec_reading;
        guint64 num_writes, num_writes_merged, num_sectors_written, num_msec_writing;
        guint64 num_io_in_progress, num_msec_doing_io, weighted_num_msec_doing_io;

        if (strlen (line) == 0)
            continue;

        /* From http://www.kernel.org/doc/Documentation/iostats.txt
         *
         * Field  1 -- # of reads completed
         *     This is the total number of reads completed successfully.
         * Field  2 -- # of reads merged, field 6 -- # of writes merged
         *     Reads and writes which are adjacent to each other may be merged for
         *     efficiency.  Thus two 4K reads may become one 8K read before it is
         *     ultimately handed to the disk, and so it will be counted (and queued)
         *     as only one I/O.  This field lets you know how often this was done.
         * Field  3 -- # of sectors read
         *     This is the total number of sectors read successfully.
         * Field  4 -- # of milliseconds spent reading
         *     This is the total number of milliseconds spent by all reads (as
         *     measured from __make_request() to end_that_request_last()).
         * Field  5 -- # of writes completed
         *     This is the total number of writes completed successfully.
         * Field  7 -- # of sectors written
         *     This is the total number of sectors written successfully.
         * Field  8 -- # of milliseconds spent writing
         *     This is the total number of milliseconds spent by all writes (as
         *     measured from __make_request() to end_that_request_last()).
         * Field  9 -- # of I/Os currently in progress
         *     The only field that should go to zero. Incremented as requests are
         *     given to appropriate struct request_queue and decremented as they finish.
         * Field 10 -- # of milliseconds spent doing I/Os
         *     This field increases so long as field 9 is nonzero.
         * Field 11 -- weighted # of milliseconds spent doing I/Os
         *     This field is incremented at each I/O start, I/O completion, I/O
         *     merge, or read of these stats by the number of I/Os in progress
         *     (field 9) times the number of milliseconds spent doing I/O since the
         *     last update of this field.  This can provide an easy measure of both
         *     I/O completion time and the backlog that may be accumulating.
         */

        num_parsed = sscanf (line,
                             "%d %d %s"
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT,
                             &dev_major, &dev_minor, dev_name,
                             &num_reads,  &num_reads_merged, &num_sectors_read, &num_msec_reading,
                             &num_writes, &num_writes_merged, &num_sectors_written, &num_msec_writing,
                             &num_io_in_progress, &num_msec_doing_io, &weighted_num_msec_doing_io);
        if (num_parsed != 14)
        {
            g_warning ("Error parsing line %d of file /proc/diskstats (num_parsed=%d): `%s'", n, num_parsed, line);
            continue;
        }

        /* skip mapped devices and partitions... otherwise we'll count their
         * I/O more than once
         *
         * TODO: the way we identify dm devices and partitions is not
         * very elegant... we should consult sysfs via libgudev1
         * instead.
         */
        if (dev_major == 253)
            continue;

        if (g_str_has_prefix (dev_name, "sd") && g_ascii_isdigit (dev_name[strlen (dev_name) - 1]))
            continue;

        sample->bytes_read += num_sectors_read * 512;
        sample->bytes_written += num_sectors_written * 512;
        sample->num_ops += num_reads_merged + num_writes_merged;
    }

    if (last != NULL)
    {
        sample->bytes_read_per_sec = calc_bandwidth (monitor, sample, last, sample->bytes_read, last->bytes_read);
        sample->bytes_written_per_sec = calc_bandwidth (monitor, sample, last, sample->bytes_written, last->bytes_written);
        sample->io_operations_per_sec = calc_bandwidth (monitor, sample, last, sample->num_ops, last->num_ops);
    }

out:
    g_strfreev (lines);
    g_free (contents);
    if (sample != NULL)
    {
        g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
        g_variant_builder_add (&builder, "d", sample->bytes_read_per_sec);
        g_variant_builder_add (&builder, "d", sample->bytes_written_per_sec);
        g_variant_builder_add (&builder, "d", sample->io_operations_per_sec);
        cockpit_resource_monitor_emit_new_sample (COCKPIT_RESOURCE_MONITOR(monitor),
                now, g_variant_builder_end (&builder));
    }

    monitor->samples_prev = monitor->samples_next;
    monitor->samples_next += 1;
    if (monitor->samples_next == monitor->samples_max)
        monitor->samples_next = 0;
}
static void
keyring_find_secrets_cb (GObject *source,
                         GAsyncResult *result,
                         gpointer user_data)
{
	Request *r = user_data;
	GError *error = NULL;
	GError *search_error = NULL;
	const char *connection_id = NULL;
	GVariantBuilder builder_setting, builder_connection;
	GVariant *settings = NULL;
	GList *list = NULL;
	GList *iter;
	gboolean hint_found = FALSE, ask = FALSE;

	r->keyring_calls--;
	if (g_cancellable_is_cancelled (r->cancellable)) {
		/* Callback already called by NM or dispose */
		request_free (r);
		return;
	}

	list = secret_service_search_finish (NULL, result, &search_error);
	connection_id = nm_connection_get_id (r->connection);

	if (g_error_matches (search_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		error = g_error_new_literal (NM_SECRET_AGENT_ERROR,
		                             NM_SECRET_AGENT_ERROR_USER_CANCELED,
		                             "The secrets request was canceled by the user");
		g_error_free (search_error);
		goto done;
	} else if (search_error) {
		error = g_error_new (NM_SECRET_AGENT_ERROR,
		                     NM_SECRET_AGENT_ERROR_FAILED,
		                     "%s.%d - failed to read secrets from keyring (%s)",
		                     __FILE__, __LINE__, search_error->message);
		g_error_free (search_error);
		goto done;
	}

	/* Only ask if we're allowed to, so that eg a connection editor which
	 * requests secrets for its UI, for a connection which doesn't have any
	 * secrets yet, doesn't trigger the applet secrets dialog.
	 */
	if (   (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
	    && g_list_length (list) == 0) {
		g_message ("No keyring secrets found for %s/%s; asking user.", connection_id, r->setting_name);
		ask_for_secrets (r);
		return;
	}

	g_variant_builder_init (&builder_setting, NM_VARIANT_TYPE_SETTING);

	/* Extract the secrets from the list of matching keyring items */
	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
		SecretItem *item = iter->data;
		SecretValue *secret;
		const char *key_name;
		GHashTable *attributes;

		secret = secret_item_get_secret (item);
		if (secret) {
			attributes = secret_item_get_attributes (item);
			key_name = g_hash_table_lookup (attributes, KEYRING_SK_TAG);
			if (!key_name) {
				g_hash_table_unref (attributes);
				secret_value_unref (secret);
				continue;
			}

			g_variant_builder_add (&builder_setting, "{sv}", key_name,
			                       g_variant_new_string (secret_value_get (secret, NULL)));

			/* See if this property matches a given hint */
			if (r->hints && r->hints[0]) {
				if (!g_strcmp0 (r->hints[0], key_name) || !g_strcmp0 (r->hints[1], key_name))
					hint_found = TRUE;
			}

			g_hash_table_unref (attributes);
			secret_value_unref (secret);
			break;
		}
	}

	/* If there were hints, and none of the hints were returned by the keyring,
	 * get some new secrets.
	 */
	if (r->flags) {
		if (r->hints && r->hints[0] && !hint_found)
			ask = TRUE;
		else if (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) {
			g_message ("New secrets for %s/%s requested; ask the user", connection_id, r->setting_name);
			ask = TRUE;
		} else if (   (r->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
			       && is_connection_always_ask (r->connection))
			ask = TRUE;
	}

	/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
	 * will contain all the individual settings hashes.
	 */
	g_variant_builder_init (&builder_connection, NM_VARIANT_TYPE_CONNECTION);
	g_variant_builder_add (&builder_connection, "{sa{sv}}", r->setting_name, &builder_setting);
	settings = g_variant_builder_end (&builder_connection);

done:
	g_list_free_full (list, g_object_unref);
	if (ask) {
		GVariantIter dict_iter;
		const char *setting_name;
		GVariant *setting_dict;

		/* Stuff all the found secrets into the connection for the UI to use */
		g_variant_iter_init (&dict_iter, settings);
		while (g_variant_iter_next (&dict_iter, "{s@a{sv}}", &setting_name, &setting_dict)) {
			nm_connection_update_secrets (r->connection,
			                              setting_name,
			                              setting_dict,
			                              NULL);
			g_variant_unref (setting_dict);
		}

		ask_for_secrets (r);
	} else {
		/* Otherwise send the secrets back to NetworkManager */
		r->get_callback (NM_SECRET_AGENT_OLD (r->agent), r->connection, error ? NULL : settings, error, r->callback_data);
		request_free (r);
	}

	if (settings)
		g_variant_unref (settings);
	g_clear_error (&error);
}
static void
add_connection (GDBusProxy *proxy, const char *con_name)
{
	GVariantBuilder connection_builder;
	GVariantBuilder setting_builder;
	char *uuid;
	const char *new_con_path;
	GVariant *ret;
	GError *error = NULL;

	/* Initialize connection GVariantBuilder */
	g_variant_builder_init (&connection_builder, G_VARIANT_TYPE ("a{sa{sv}}"));

	/* Build up the 'connection' Setting */
	g_variant_builder_init (&setting_builder, G_VARIANT_TYPE ("a{sv}"));

	uuid = nm_utils_uuid_generate ();
	g_variant_builder_add (&setting_builder, "{sv}",
	                       NM_SETTING_CONNECTION_UUID,
	                       g_variant_new_string (uuid));
	g_free (uuid);

	g_variant_builder_add (&setting_builder, "{sv}",
	                       NM_SETTING_CONNECTION_ID,
	                       g_variant_new_string (con_name));
	g_variant_builder_add (&setting_builder, "{sv}",
	                       NM_SETTING_CONNECTION_TYPE,
	                       g_variant_new_string (NM_SETTING_WIRED_SETTING_NAME));

	g_variant_builder_add (&connection_builder, "{sa{sv}}",
	                       NM_SETTING_CONNECTION_SETTING_NAME,
	                       &setting_builder);

	/* Add the (empty) 'wired' Setting */
	g_variant_builder_init (&setting_builder, G_VARIANT_TYPE ("a{sv}"));
	g_variant_builder_add (&connection_builder, "{sa{sv}}",
	                       NM_SETTING_WIRED_SETTING_NAME,
	                       &setting_builder);

	/* Build up the 'ipv4' Setting */
	g_variant_builder_init (&setting_builder, G_VARIANT_TYPE ("a{sv}"));
	g_variant_builder_add (&setting_builder, "{sv}",
	                       NM_SETTING_IP_CONFIG_METHOD,
	                       g_variant_new_string (NM_SETTING_IP4_CONFIG_METHOD_AUTO));
	g_variant_builder_add (&connection_builder, "{sa{sv}}",
	                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
	                       &setting_builder);

	/* Call AddConnection with the connection dictionary as argument.
	 * (g_variant_new() will consume the floating GVariant returned from
	 * &connection_builder, and g_dbus_proxy_call_sync() will consume the
	 * floating variant returned from g_variant_new(), so no cleanup is needed.
	 */
	ret = g_dbus_proxy_call_sync (proxy,
	                              "AddConnection",
	                              g_variant_new ("(a{sa{sv}})", &connection_builder),
	                              G_DBUS_CALL_FLAGS_NONE, -1,
	                              NULL, &error);
	if (ret) {
		g_variant_get (ret, "(&o)", &new_con_path);
		g_print ("Added: %s\n", new_con_path);
		g_variant_unref (ret);
	} else {
		g_dbus_error_strip_remote_error (error);
		g_print ("Error adding connection: %s\n", error->message);
		g_clear_error (&error);
	}
}
示例#13
0
文件: api.c 项目: ant9000/libsigrok
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
		const struct sr_channel_group *cg)
{
	struct dev_context *devc;
	struct sr_channel *ch;
	struct channel_spec *ch_spec;
	GVariant *gvar;
	GVariantBuilder gvb;
	int ret, i;
	const char *s[16];

	/* Always available, even without sdi. */
	if (key == SR_CONF_SCAN_OPTIONS) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
		return SR_OK;
	} else if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
				drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
		return SR_OK;
	}

	if (!sdi)
		return SR_ERR_ARG;
	devc = sdi->priv;

	ret = SR_OK;
	if (!cg) {
		/* No channel group: global options. */
		switch (key) {
		case SR_CONF_DEVICE_OPTIONS:
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
					devc->device->devopts, devc->device->num_devopts,
					sizeof(uint32_t));
			break;
		case SR_CONF_OUTPUT_CHANNEL_CONFIG:
			/* Not used. */
			i = 0;
			if (devc->device->features & PPS_INDEPENDENT)
				s[i++] = "Independent";
			if (devc->device->features & PPS_SERIES)
				s[i++] = "Series";
			if (devc->device->features & PPS_PARALLEL)
				s[i++] = "Parallel";
			if (i == 0) {
				/*
				 * Shouldn't happen: independent-only devices
				 * shouldn't advertise this option at all.
				 */
				return SR_ERR_NA;
			}
			*data = g_variant_new_strv(s, i);
			break;
		default:
			return SR_ERR_NA;
		}
	} else {
		/* Channel group specified. */
		/*
		 * Per-channel-group options depending on a channel are actually
		 * done with the first channel. Channel groups in PPS can have
		 * more than one channel, but they will typically be of equal
		 * specification for use in series or parallel mode.
		 */
		ch = cg->channels->data;

		switch (key) {
		case SR_CONF_DEVICE_OPTIONS:
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
					devc->device->devopts_cg, devc->device->num_devopts_cg,
					sizeof(uint32_t));
			break;
		case SR_CONF_OUTPUT_VOLTAGE_TARGET:
			ch_spec = &(devc->device->channels[ch->index]);
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
			/* Min, max, write resolution. */
			for (i = 0; i < 3; i++) {
				gvar = g_variant_new_double(ch_spec->voltage[i]);
				g_variant_builder_add_value(&gvb, gvar);
			}
			*data = g_variant_builder_end(&gvb);
			break;
		case SR_CONF_OUTPUT_CURRENT_LIMIT:
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
			/* Min, max, step. */
			for (i = 0; i < 3; i++) {
				ch_spec = &(devc->device->channels[ch->index]);
				gvar = g_variant_new_double(ch_spec->current[i]);
				g_variant_builder_add_value(&gvb, gvar);
			}
			*data = g_variant_builder_end(&gvb);
			break;
		default:
			return SR_ERR_NA;
		}
	}

	return ret;
}
gboolean
flatpak_builtin_build_commit_from (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  g_autoptr(GOptionContext) context = NULL;
  g_autoptr(GFile) dst_repofile = NULL;
  g_autoptr(OstreeRepo) dst_repo = NULL;
  g_autoptr(GFile) src_repofile = NULL;
  g_autoptr(OstreeRepo) src_repo = NULL;
  g_autofree char *src_repo_uri = NULL;
  const char *dst_repo_arg;
  const char **dst_refs;
  int n_dst_refs = 0;
  g_autoptr(FlatpakRepoTransaction) transaction = NULL;
  g_autoptr(GPtrArray) src_refs = NULL;
  g_autoptr(GPtrArray) resolved_src_refs = NULL;
  OstreeRepoCommitState src_commit_state;
  struct timespec ts;
  guint64 timestamp;
  int i;

  context = g_option_context_new (_("DST-REPO [DST-REF…] - Make a new commit from existing commits"));
  g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);

  if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
    return FALSE;

  if (argc < 2)
    return usage_error (context, _("DST-REPO must be specified"), error);

  dst_repo_arg = argv[1];

  dst_refs = (const char **) argv + 2;
  n_dst_refs = argc - 2;

  if (opt_src_repo == NULL && n_dst_refs != 1)
    return usage_error (context, _("If --src-repo is not specified, exactly one destination ref must be specified"), error);

  if (opt_src_ref != NULL && n_dst_refs != 1)
    return usage_error (context, _("If --src-ref is specified, exactly one destination ref must be specified"), error);

  if (opt_src_repo == NULL && opt_src_ref == NULL)
    return flatpak_fail (error, _("Either --src-repo or --src-ref must be specified."));

  if (opt_timestamp)
    {
      if (!parse_datetime (&ts, opt_timestamp, NULL))
        return flatpak_fail (error, _("Could not parse '%s'"), opt_timestamp);
    }

  dst_repofile = g_file_new_for_commandline_arg (dst_repo_arg);
  if (!g_file_query_exists (dst_repofile, cancellable))
    return flatpak_fail (error, _("'%s' is not a valid repository"), dst_repo_arg);

  dst_repo = ostree_repo_new (dst_repofile);
  if (!ostree_repo_open (dst_repo, cancellable, error))
    return FALSE;

  if (opt_disable_fsync)
    ostree_repo_set_disable_fsync (dst_repo, TRUE);

  if (opt_src_repo)
    {
      src_repofile = g_file_new_for_commandline_arg (opt_src_repo);
      if (!g_file_query_exists (src_repofile, cancellable))
        return flatpak_fail (error, _("'%s' is not a valid repository"), opt_src_repo);

      src_repo_uri = g_file_get_uri (src_repofile);
      src_repo = ostree_repo_new (src_repofile);
      if (!ostree_repo_open (src_repo, cancellable, error))
        return FALSE;
    }
  else
    {
      src_repo = g_object_ref (dst_repo);
    }

  src_refs = g_ptr_array_new_with_free_func (g_free);
  if (opt_src_ref)
    {
      g_assert (n_dst_refs == 1);
      g_ptr_array_add (src_refs, g_strdup (opt_src_ref));
    }
  else
    {
      g_assert (opt_src_repo != NULL);
      if (n_dst_refs == 0)
        {
          g_autofree const char **keys = NULL;
          g_autoptr(GHashTable) all_src_refs = NULL;

          if (!ostree_repo_list_refs (src_repo, NULL, &all_src_refs,
                                      cancellable, error))
            return FALSE;

          keys = (const char **) g_hash_table_get_keys_as_array (all_src_refs, NULL);

          for (i = 0; keys[i] != NULL; i++)
            {
              if (g_str_has_prefix (keys[i], "runtime/") ||
                  g_str_has_prefix (keys[i], "app/"))
                g_ptr_array_add (src_refs, g_strdup (keys[i]));
            }
          n_dst_refs = src_refs->len;
          dst_refs = (const char **) src_refs->pdata;
        }
      else
        {
          for (i = 0; i < n_dst_refs; i++)
            g_ptr_array_add (src_refs, g_strdup (dst_refs[i]));
        }
    }

  resolved_src_refs = g_ptr_array_new_with_free_func (g_free);
  for (i = 0; i < src_refs->len; i++)
    {
      const char *src_ref = g_ptr_array_index (src_refs, i);
      char *resolved_ref;

      if (!ostree_repo_resolve_rev (src_repo, src_ref, FALSE, &resolved_ref, error))
        return FALSE;

      g_ptr_array_add (resolved_src_refs, resolved_ref);
    }

  if (src_repo_uri != NULL)
    {
      OstreeRepoPullFlags pullflags = 0;
      GVariantBuilder builder;
      g_autoptr(OstreeAsyncProgress) progress = NULL;
      g_auto(GLnxConsoleRef) console = { 0, };
      g_autoptr(GVariant) options = NULL;
      gboolean res;

      if (opt_untrusted)
        pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED;

      glnx_console_lock (&console);
      if (console.is_tty)
        progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);

      g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
      g_variant_builder_add (&builder, "{s@v}", "flags",
                             g_variant_new_variant (g_variant_new_int32 (pullflags)));
      g_variant_builder_add (&builder, "{s@v}", "refs",
                             g_variant_new_variant (g_variant_new_strv ((const char * const *) resolved_src_refs->pdata,
                                                                        resolved_src_refs->len)));
      g_variant_builder_add (&builder, "{s@v}", "depth",
                             g_variant_new_variant (g_variant_new_int32 (0)));

      options = g_variant_ref_sink (g_variant_builder_end (&builder));
      res = ostree_repo_pull_with_options (dst_repo, src_repo_uri,
                                           options,
                                           progress,
                                           cancellable, error);

      if (progress)
        ostree_async_progress_finish (progress);

      if (!res)
        return FALSE;
    }

  /* By now we have the commit with commit_id==resolved_ref and dependencies in dst_repo. We now create a new
   * commit based on the toplevel tree ref from that commit.
   * This is equivalent to:
   *   ostree commit --skip-if-unchanged --repo=${destrepo} --tree=ref=${resolved_ref}
   */

  transaction = flatpak_repo_transaction_start (dst_repo, cancellable, error);
  if (transaction == NULL)
    return FALSE;

  for (i = 0; i < resolved_src_refs->len; i++)
    {
      const char *dst_ref = dst_refs[i];
      const char *resolved_ref = g_ptr_array_index (resolved_src_refs, i);
      g_autofree char *dst_parent = NULL;
      g_autoptr(GFile) dst_parent_root = NULL;
      g_autoptr(GFile) src_ref_root = NULL;
      g_autoptr(GVariant) src_commitv = NULL;
      g_autoptr(GVariant) dst_commitv = NULL;
      g_autoptr(OstreeMutableTree) mtree = NULL;
      g_autoptr(GFile) dst_root = NULL;
      g_autoptr(GVariant) commitv_metadata = NULL;
      g_autoptr(GVariant) metadata = NULL;
      const char *subject;
      const char *body;
      g_autofree char *commit_checksum = NULL;
      GVariantBuilder metadata_builder;
      gint j;
      const char *dst_collection_id = NULL;
      const char *main_collection_id = NULL;
      g_autoptr(GPtrArray) collection_ids = NULL;

      if (!ostree_repo_resolve_rev (dst_repo, dst_ref, TRUE, &dst_parent, error))
        return FALSE;

      if (dst_parent != NULL &&
          !ostree_repo_read_commit (dst_repo, dst_parent, &dst_parent_root, NULL, cancellable, error))
        return FALSE;

      if (!ostree_repo_read_commit (dst_repo, resolved_ref, &src_ref_root, NULL, cancellable, error))
        return FALSE;

      if (!ostree_repo_load_commit (dst_repo, resolved_ref, &src_commitv, &src_commit_state, error))
        return FALSE;

      if (src_commit_state & OSTREE_REPO_COMMIT_STATE_PARTIAL)
        return flatpak_fail (error, _("Can't commit from partial source commit."));

      /* Don't create a new commit if this is the same tree */
      if (!opt_force && dst_parent_root != NULL && g_file_equal (dst_parent_root, src_ref_root))
        {
          g_print (_("%s: no change\n"), dst_ref);
          continue;
        }

      mtree = ostree_mutable_tree_new ();
      if (!ostree_repo_write_directory_to_mtree (dst_repo, src_ref_root, mtree, NULL,
                                                 cancellable, error))
        return FALSE;

      if (!ostree_repo_write_mtree (dst_repo, mtree, &dst_root, cancellable, error))
        return FALSE;

      commitv_metadata = g_variant_get_child_value (src_commitv, 0);

      g_variant_get_child (src_commitv, 3, "&s", &subject);
      if (opt_subject)
        subject = (const char *) opt_subject;
      g_variant_get_child (src_commitv, 4, "&s", &body);
      if (opt_body)
        body = (const char *) opt_body;

      dst_collection_id = ostree_repo_get_collection_id (dst_repo);

      collection_ids = g_ptr_array_new_with_free_func (g_free);
      if (dst_collection_id)
        {
          main_collection_id = dst_collection_id;
          g_ptr_array_add (collection_ids, g_strdup (dst_collection_id));
        }

      if (opt_extra_collection_ids != NULL)
        {
          for (j = 0; opt_extra_collection_ids[j] != NULL; j++)
            {
              const char *cid = opt_extra_collection_ids[j];
              if (main_collection_id == NULL)
                main_collection_id = cid; /* Fall back to first arg */

              if (g_strcmp0 (cid, dst_collection_id) != 0)
                g_ptr_array_add (collection_ids, g_strdup (cid));
            }
        }

      g_ptr_array_sort (collection_ids, (GCompareFunc)flatpak_strcmp0_ptr);

      /* Copy old metadata */
      g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));

      /* Bindings. xa.ref is deprecated but added anyway for backwards compatibility. */
      g_variant_builder_add (&metadata_builder, "{sv}", "ostree.collection-binding",
                             g_variant_new_string (main_collection_id ? main_collection_id : ""));
      if (collection_ids->len > 0)
        {
          g_autoptr(GVariantBuilder) cr_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)"));

          for (j = 0; j < collection_ids->len; j++)
            g_variant_builder_add (cr_builder, "(ss)", g_ptr_array_index (collection_ids, j), dst_ref);

          g_variant_builder_add (&metadata_builder, "{sv}", "ostree.collection-refs-binding",
                                 g_variant_builder_end (cr_builder));
        }
      g_variant_builder_add (&metadata_builder, "{sv}", "ostree.ref-binding",
                             g_variant_new_strv (&dst_ref, 1));
      g_variant_builder_add (&metadata_builder, "{sv}", "xa.ref", g_variant_new_string (dst_ref));

      /* Record the source commit. This is nice to have, but it also
         means the commit-from gets a different commit id, which
         avoids problems with e.g.  sharing .commitmeta files
         (signatures) */
      g_variant_builder_add (&metadata_builder, "{sv}", "xa.from_commit", g_variant_new_string (resolved_ref));

      for (j = 0; j < g_variant_n_children (commitv_metadata); j++)
        {
          g_autoptr(GVariant) child = g_variant_get_child_value (commitv_metadata, j);
          g_autoptr(GVariant) keyv = g_variant_get_child_value (child, 0);
          const char *key = g_variant_get_string (keyv, NULL);

          if (strcmp (key, "xa.ref") == 0 ||
              strcmp (key, "xa.from_commit") == 0 ||
              strcmp (key, "ostree.collection-binding") == 0 ||
              strcmp (key, "ostree.collection-refs-binding") == 0 ||
              strcmp (key, "ostree.ref-binding") == 0)
            continue;

          if (opt_endoflife &&
              strcmp (key, OSTREE_COMMIT_META_KEY_ENDOFLIFE) == 0)
            continue;

          g_variant_builder_add_value (&metadata_builder, child);
        }

      if (opt_endoflife && *opt_endoflife)
        g_variant_builder_add (&metadata_builder, "{sv}", OSTREE_COMMIT_META_KEY_ENDOFLIFE,
                               g_variant_new_string (opt_endoflife));

      timestamp = ostree_commit_get_timestamp (src_commitv);
      if (opt_timestamp)
        timestamp = ts.tv_sec;

      metadata = g_variant_ref_sink (g_variant_builder_end (&metadata_builder));
      if (!ostree_repo_write_commit_with_time (dst_repo, dst_parent, subject, body, metadata,
                                               OSTREE_REPO_FILE (dst_root),
                                               timestamp,
                                               &commit_checksum, cancellable, error))
        return FALSE;

      g_print ("%s: %s\n", dst_ref, commit_checksum);

      if (!ostree_repo_load_commit (dst_repo, commit_checksum, &dst_commitv, NULL, error))
        return FALSE;

      /* This doesn't copy the detached metadata. I'm not sure if this is a problem.
       * The main thing there is commit signatures, and we can't copy those, as the commit hash changes.
       */

      if (opt_gpg_key_ids)
        {
          char **iter;

          for (iter = opt_gpg_key_ids; iter && *iter; iter++)
            {
              const char *keyid = *iter;
              g_autoptr(GError) my_error = NULL;

              if (!ostree_repo_sign_commit (dst_repo,
                                            commit_checksum,
                                            keyid,
                                            opt_gpg_homedir,
                                            cancellable,
                                            &my_error) &&
                  !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
                {
                  g_propagate_error (error, g_steal_pointer (&my_error));
                  return FALSE;
                }
            }
        }

      if (dst_collection_id != NULL)
        {
          OstreeCollectionRef ref = { (char *) dst_collection_id, (char *) dst_ref };
          ostree_repo_transaction_set_collection_ref (dst_repo, &ref, commit_checksum);
        }
      else
        {
          ostree_repo_transaction_set_ref (dst_repo, NULL, dst_ref, commit_checksum);
        }

      if (opt_extra_collection_ids)
        {
          for (j = 0; opt_extra_collection_ids[j] != NULL; j++)
            {
              OstreeCollectionRef ref = { (char *) opt_extra_collection_ids[j], (char *) dst_ref };
              ostree_repo_transaction_set_collection_ref (dst_repo, &ref, commit_checksum);
            }
        }

      /* Copy + Rewrite any deltas */
      {
        const char *from[2];
        gsize j, n_from = 0;

        if (dst_parent != NULL)
          from[n_from++] = dst_parent;
        from[n_from++] = NULL;

        for (j = 0; j < n_from; j++)
          {
            g_autoptr(GError) local_error = NULL;
            if (!rewrite_delta (src_repo, resolved_ref, dst_repo, commit_checksum, dst_commitv, from[j], &local_error))
              g_debug ("Failed to copy delta: %s", local_error->message);
          }
      }
    }

  if (!ostree_repo_commit_transaction (dst_repo, NULL, cancellable, error))
    return FALSE;

  if (opt_update_appstream &&
      !flatpak_repo_generate_appstream (dst_repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error))
    return FALSE;

  if (!opt_no_update_summary &&
      !flatpak_repo_update (dst_repo,
                            (const char **) opt_gpg_key_ids,
                            opt_gpg_homedir,
                            cancellable,
                            error))
    return FALSE;

  return TRUE;
}
示例#15
0
static guint
gtk_application_impl_dbus_inhibit (GtkApplicationImpl         *impl,
                                   GtkWindow                  *window,
                                   GtkApplicationInhibitFlags  flags,
                                   const gchar                *reason)
{
  GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) impl;
  GVariant *res;
  GError *error = NULL;
  guint cookie;
  static gboolean warned = FALSE;

  if (dbus->sm_proxy)
    {
      res = g_dbus_proxy_call_sync (dbus->sm_proxy,
                                    "Inhibit",
                                    g_variant_new ("(s@usu)",
                                                   dbus->application_id,
                                                   window ? gtk_application_impl_dbus_get_window_system_id (dbus, window) : g_variant_new_uint32 (0),
                                                   reason,
                                                   flags),
                                    G_DBUS_CALL_FLAGS_NONE,
                                    G_MAXINT,
                                    NULL,
                                    &error);

      if (res)
        {
          g_variant_get (res, "(u)", &cookie);
          g_variant_unref (res);
          return cookie;
        }

      if (error)
        {
          if (!warned)
            {
              g_warning ("Calling %s.Inhibit failed: %s",
                         g_dbus_proxy_get_interface_name (dbus->sm_proxy),
                         error->message);
              warned = TRUE;
            }
          g_clear_error (&error);
        }
    }
  else if (dbus->inhibit_proxy)
    {
      GVariantBuilder options;

      g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
      g_variant_builder_add (&options, "{sv}", "reason", g_variant_new_string (reason));
      res = g_dbus_proxy_call_sync (dbus->inhibit_proxy,
                                    "Inhibit",
                                    g_variant_new ("(su@a{sv})",
                                                   "", /* window */
                                                   flags,
                                                   g_variant_builder_end (&options)),
                                    G_DBUS_CALL_FLAGS_NONE,
                                    G_MAXINT,
                                    NULL,
                                    &error);
      if (res)
        {
          InhibitHandle *handle;

          handle = g_new (InhibitHandle, 1);
          handle->cookie = ++next_cookie;

          g_variant_get (res, "(o)", &handle->handle);
          g_variant_unref (res);

          dbus->inhibit_handles = g_slist_prepend (dbus->inhibit_handles, handle);

          return handle->cookie;
        }

      if (error)
        {
          if (!warned)
            {
              g_warning ("Calling %s.Inhibit failed: %s",
                         g_dbus_proxy_get_interface_name (dbus->inhibit_proxy),
                         error->message);
              warned = TRUE;
            }
          g_clear_error (&error);
        }
    }

  return 0;
}
static void
write_translations_dictionary (GList * licenses, const gchar * dict_filename)
{
  /* maps C string => (dictionary of: locale => translation) */
  GVariantBuilder array;
  /* maps C string => boolean (if it's in the dictionary already */
  GHashTable *translations;
  GVariant *var;
  GList *l;
  FILE *f;

  /* sort langs for prettiness / to make variant dumps easier to read */
  langs = g_list_sort (langs, (GCompareFunc) strcmp);

  g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);

  translations = g_hash_table_new (g_str_hash, g_str_equal);

  for (l = licenses; l != NULL; l = l->next) {
    const gchar *en;
    License *license;

    license = l->data;

    if (license->packed_into_source)
      continue;

    /* add title + translations */
    en = g_hash_table_lookup (license->titles, "en");
    g_assert (en != NULL);

    /* check if we already have added translations for this string */
    if (!g_hash_table_lookup (translations, (gpointer) en)) {
      GVariant *trans;

      trans = create_translation_dict (license->titles, en);
      if (trans != NULL) {
        g_variant_builder_add_value (&array,
            g_variant_new_dict_entry (g_variant_new_string (en), trans));
        g_hash_table_insert (translations, (gpointer) en,
            GINT_TO_POINTER (TRUE));
      }
    }

    /* add description + translations */
    if (license->descriptions == NULL)
      continue;

    en = g_hash_table_lookup (license->descriptions, "en");
    g_assert (en != NULL);

    /* check if we already have added translations for this string */
    if (!g_hash_table_lookup (translations, (gpointer) en)) {
      GVariant *trans;

      trans = create_translation_dict (license->descriptions, en);
      if (trans != NULL) {
        g_variant_builder_add_value (&array,
            g_variant_new_dict_entry (g_variant_new_string (en), trans));
        g_hash_table_insert (translations, (gpointer) en,
            GINT_TO_POINTER (TRUE));
      }
    }
  }

  var = g_variant_builder_end (&array);

  f = fopen (dict_filename, "wb");
  if (fwrite (g_variant_get_data (var), g_variant_get_size (var), 1, f) != 1) {
    g_error ("failed to write dict to file: %s", g_strerror (errno));
  }
  fclose (f);

  g_printerr ("Wrote dictionary to %s, size: %u, type: %s\n", dict_filename,
      (guint) g_variant_get_size (var), (gchar *) g_variant_get_type (var));

  g_variant_unref (var);
  g_hash_table_destroy (translations);
}
示例#17
0
GVariant *
nm_lldp_listener_get_neighbors (NMLldpListener *self)
{
	GVariantBuilder array_builder, neigh_builder;
	GHashTableIter iter;
	NMLldpListenerPrivate *priv;
	LLDPNeighbor *neigh;
	char *dest_str = NULL;

	priv = NM_LLDP_LISTENER_GET_PRIVATE (self);

	if (priv->variant)
		goto out;

	g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
	g_hash_table_iter_init (&iter, priv->lldp_neighbors);

	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &neigh)) {
		GHashTableIter val_iter;
		gpointer key, val;

		g_variant_builder_init (&neigh_builder, G_VARIANT_TYPE ("a{sv}"));

		g_variant_builder_add (&neigh_builder, "{sv}",
		                       NM_LLDP_ATTR_CHASSIS_ID_TYPE,
		                       g_variant_new_uint32 (neigh->chassis_id_type));
		g_variant_builder_add (&neigh_builder, "{sv}",
		                       NM_LLDP_ATTR_CHASSIS_ID,
		                       g_variant_new_string (neigh->chassis_id));
		g_variant_builder_add (&neigh_builder, "{sv}",
		                       NM_LLDP_ATTR_PORT_ID_TYPE,
		                       g_variant_new_uint32 (neigh->port_id_type));
		g_variant_builder_add (&neigh_builder, "{sv}",
		                       NM_LLDP_ATTR_PORT_ID,
		                       g_variant_new_string (neigh->port_id));

		switch (neigh->dest) {
		case SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE:
			dest_str = NM_LLDP_DEST_NEAREST_BRIDGE;
			break;
		case SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE:
			dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE;
			break;
		case SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE:
			dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE;
			break;
		}

		if (dest_str) {
			g_variant_builder_add (&neigh_builder, "{sv}",
			                       NM_LLDP_ATTR_DESTINATION,
			                       g_variant_new_string (dest_str));
		}

		g_hash_table_iter_init (&val_iter, neigh->tlvs);
		while (g_hash_table_iter_next (&val_iter, &key, &val)) {
			GValue *item = val;

			if (G_VALUE_HOLDS_STRING (item)) {
				g_variant_builder_add (&neigh_builder, "{sv}",
				                       key,
				                       g_variant_new_string (g_value_get_string (item)));
			} else if (G_VALUE_HOLDS_UINT (item)) {
				g_variant_builder_add (&neigh_builder, "{sv}",
				                       key,
				                       g_variant_new_uint32 (g_value_get_uint (item)));
			}
		}

		g_variant_builder_add (&array_builder, "a{sv}", &neigh_builder);
	}

	priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder));

out:
	return priv->variant;
}
static void
send_dbus_event (SensorData     *data,
		 PropertiesMask  mask)
{
	GVariantBuilder props_builder;
	GVariant *props_changed = NULL;

	g_assert (data->connection);

	if (mask == 0)
		return;

	g_assert ((mask & PROP_ALL) == 0 || (mask & PROP_ALL_COMPASS) == 0);

	g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));

	if (mask & PROP_HAS_ACCELEROMETER) {
		gboolean has_accel;

		has_accel = driver_type_exists (data, DRIVER_TYPE_ACCEL);
		g_variant_builder_add (&props_builder, "{sv}", "HasAccelerometer",
				       g_variant_new_boolean (has_accel));

		/* Send the orientation when the device appears */
		if (has_accel)
			mask |= PROP_ACCELEROMETER_ORIENTATION;
		else
			data->previous_orientation = ORIENTATION_UNDEFINED;
	}

	if (mask & PROP_ACCELEROMETER_ORIENTATION) {
		g_variant_builder_add (&props_builder, "{sv}", "AccelerometerOrientation",
				       g_variant_new_string (orientation_to_string (data->previous_orientation)));
	}

	if (mask & PROP_HAS_AMBIENT_LIGHT) {
		gboolean has_als;

		has_als = driver_type_exists (data, DRIVER_TYPE_LIGHT);
		g_variant_builder_add (&props_builder, "{sv}", "HasAmbientLight",
				       g_variant_new_boolean (has_als));

		/* Send the light level when the device appears */
		if (has_als)
			mask |= PROP_LIGHT_LEVEL;
	}

	if (mask & PROP_LIGHT_LEVEL) {
		g_variant_builder_add (&props_builder, "{sv}", "LightLevelUnit",
				       g_variant_new_string (data->uses_lux ? "lux" : "vendor"));
		g_variant_builder_add (&props_builder, "{sv}", "LightLevel",
				       g_variant_new_double (data->previous_level));
	}

	if (mask & PROP_HAS_COMPASS) {
		gboolean has_compass;

		has_compass = driver_type_exists (data, DRIVER_TYPE_COMPASS);
		g_variant_builder_add (&props_builder, "{sv}", "HasCompass",
				       g_variant_new_boolean (has_compass));

		/* Send the heading when the device appears */
		if (has_compass)
			mask |= PROP_COMPASS_HEADING;
	}

	if (mask & PROP_COMPASS_HEADING) {
		g_variant_builder_add (&props_builder, "{sv}", "CompassHeading",
				       g_variant_new_double (data->previous_heading));
	}

	props_changed = g_variant_new ("(s@a{sv}@as)", (mask & PROP_ALL) ? SENSOR_PROXY_IFACE_NAME : SENSOR_PROXY_COMPASS_IFACE_NAME,
				       g_variant_builder_end (&props_builder),
				       g_variant_new_strv (NULL, 0));

	g_dbus_connection_emit_signal (data->connection,
				       NULL,
				       (mask & PROP_ALL) ? SENSOR_PROXY_DBUS_PATH : SENSOR_PROXY_COMPASS_DBUS_PATH,
				       "org.freedesktop.DBus.Properties",
				       "PropertiesChanged",
				       props_changed, NULL);
}
示例#19
0
static void
name_lost_cb (GDBusConnection *connection,
              const char *name,
              gpointer user_data)
{
	OwnData *data = (OwnData *) user_data;
	GError *error = NULL;
	char **envv;
	int envc, i;
	GVariantBuilder builder;
	GVariant *value;
	GString *string;
	char *s;
	gsize len;

	_terminal_debug_print (TERMINAL_DEBUG_FACTORY,
	                       "Lost the name %s on the session bus\n", name);

	/* Couldn't get the connection? No way to continue! */
	if (connection == NULL)
	{
		data->exit_code = EXIT_FAILURE;
		gtk_main_quit ();
		return;
	}

	if (data->options == NULL)
	{
		/* Already handled */
		data->exit_code = EXIT_SUCCESS;
		gtk_main_quit ();
		return;
	}

	_terminal_debug_print (TERMINAL_DEBUG_FACTORY,
	                       "Forwarding arguments to existing instance\n");

    g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ayayayayiay)"));
    
	g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->default_working_dir));
	g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->display_name));
	g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->startup_id));

	string = g_string_new (NULL);
	envv = g_listenv ();
	envc = g_strv_length (envv);
	for (i = 0; i < envc; ++i)
	{
		const char *value;

		value = g_getenv (envv[i]);
		if (value == NULL)
			continue;

		if (i > 0)
			g_string_append_c (string, '\0');

		g_string_append_printf (string, "%s=%s", envv[i], value);
	}

	len = string->len;
	s = g_string_free (string, FALSE);
	g_variant_builder_add (&builder, "@ay",
	                       g_variant_new_from_data (G_VARIANT_TYPE ("ay"), s, len, TRUE, g_free, s));

    g_variant_builder_add (&builder, "@i", g_variant_new_int32 (data->options->initial_workspace));

	string = g_string_new (NULL);

	for (i = 0; i < data->argc; ++i)
	{
		if (i > 0)
			g_string_append_c (string, '\0');
		g_string_append (string, data->argv[i]);
	}

	len = string->len;
	s = g_string_free (string, FALSE);
	g_variant_builder_add (&builder, "@ay",
	                       g_variant_new_from_data (G_VARIANT_TYPE ("ay"), s, len, TRUE, g_free, s));

	value = g_dbus_connection_call_sync (connection,
	                                     data->factory_name,
	                                     TERMINAL_FACTORY_SERVICE_PATH,
	                                     TERMINAL_FACTORY_INTERFACE_NAME,
	                                     "HandleArguments",
	                                     g_variant_builder_end (&builder),
	                                     G_VARIANT_TYPE ("()"),
	                                     G_DBUS_CALL_FLAGS_NONE,
	                                     -1,
	                                     NULL,
	                                     &error);
	if (value == NULL)
	{
		g_printerr ("Failed to forward arguments: %s\n", error->message);
		g_error_free (error);
		data->exit_code = EXIT_FAILURE;
		gtk_main_quit ();
	}
	else
	{
		g_variant_unref (value);
		data->exit_code = EXIT_SUCCESS;
	}

	terminal_options_free (data->options);
	data->options = NULL;

	gtk_main_quit ();
}
示例#20
0
文件: monitor.c 项目: gcampax/mutter
static gboolean
meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
                                           GDBusMethodInvocation *invocation)
{
  MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (skeleton);
  GVariantBuilder crtc_builder, output_builder, mode_builder;
  unsigned int i, j;

  g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})"));
  g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausauaua{sv})"));
  g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuud)"));

  for (i = 0; i < manager->n_crtcs; i++)
    {
      MetaCRTC *crtc = &manager->crtcs[i];
      GVariantBuilder transforms;

      g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
      for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
        if (crtc->all_transforms & (1 << j))
          g_variant_builder_add (&transforms, "u", j);

      g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
                             i, /* ID */
                             (gint64)crtc->crtc_id,
                             (int)crtc->rect.x,
                             (int)crtc->rect.y,
                             (int)crtc->rect.width,
                             (int)crtc->rect.height,
                             (int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
                             (guint32)crtc->transform,
                             &transforms,
                             NULL /* properties */);
    }

  for (i = 0; i < manager->n_outputs; i++)
    {
      MetaOutput *output = &manager->outputs[i];
      GVariantBuilder crtcs, modes, clones, properties;
      GBytes *edid;
      char *edid_file;

      g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
      for (j = 0; j < output->n_possible_crtcs; j++)
        g_variant_builder_add (&crtcs, "u",
                               (unsigned)(output->possible_crtcs[j] - manager->crtcs));

      g_variant_builder_init (&modes, G_VARIANT_TYPE ("au"));
      for (j = 0; j < output->n_modes; j++)
        g_variant_builder_add (&modes, "u",
                               (unsigned)(output->modes[j] - manager->modes));

      g_variant_builder_init (&clones, G_VARIANT_TYPE ("au"));
      for (j = 0; j < output->n_possible_clones; j++)
        g_variant_builder_add (&clones, "u",
                               (unsigned)(output->possible_clones[j] - manager->outputs));

      g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}"));
      g_variant_builder_add (&properties, "{sv}", "vendor",
                             g_variant_new_string (output->vendor));
      g_variant_builder_add (&properties, "{sv}", "product",
                             g_variant_new_string (output->product));
      g_variant_builder_add (&properties, "{sv}", "serial",
                             g_variant_new_string (output->serial));
      g_variant_builder_add (&properties, "{sv}", "width-mm",
                             g_variant_new_int32 (output->width_mm));
      g_variant_builder_add (&properties, "{sv}", "height-mm",
                             g_variant_new_int32 (output->height_mm));
      g_variant_builder_add (&properties, "{sv}", "display-name",
                             g_variant_new_take_string (make_display_name (manager, output)));
      g_variant_builder_add (&properties, "{sv}", "backlight",
                             g_variant_new_int32 (output->backlight));
      g_variant_builder_add (&properties, "{sv}", "primary",
                             g_variant_new_boolean (output->is_primary));
      g_variant_builder_add (&properties, "{sv}", "presentation",
                             g_variant_new_boolean (output->is_presentation));

      edid_file = manager_class->get_edid_file (manager, output);
      if (edid_file)
        {
          g_variant_builder_add (&properties, "{sv}", "edid-file",
                                 g_variant_new_take_string (edid_file));
        }
      else
        {
          edid = manager_class->read_edid (manager, output);

          if (edid)
            {
              g_variant_builder_add (&properties, "{sv}", "edid",
                                     g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"),
                                                               edid, TRUE));
              g_bytes_unref (edid);
            }
        }

      g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
                             i, /* ID */
                             (gint64)output->output_id,
                             (int)(output->crtc ? output->crtc - manager->crtcs : -1),
                             &crtcs,
                             output->name,
                             &modes,
                             &clones,
                             &properties);
    }

  for (i = 0; i < manager->n_modes; i++)
    {
      MetaMonitorMode *mode = &manager->modes[i];

      g_variant_builder_add (&mode_builder, "(uxuud)",
                             i, /* ID */
                             (gint64)mode->mode_id,
                             (guint32)mode->width,
                             (guint32)mode->height,
                             (double)mode->refresh_rate);
    }

  meta_dbus_display_config_complete_get_resources (skeleton,
                                                   invocation,
                                                   manager->serial,
                                                   g_variant_builder_end (&crtc_builder),
                                                   g_variant_builder_end (&output_builder),
                                                   g_variant_builder_end (&mode_builder),
                                                   manager->max_screen_width,
                                                   manager->max_screen_height);
  return TRUE;
}
static gboolean
writeback_dispatcher_writeback_file (TrackerMinerFS *fs,
                                     GFile          *file,
                                     GStrv           rdf_types,
                                     GPtrArray      *results,
                                     GCancellable   *cancellable,
                                     gpointer        user_data)
{
	TrackerWritebackDispatcher *self = user_data;
	TrackerWritebackDispatcherPrivate *priv;
	gchar *uri;
	guint i;
	GVariantBuilder builder;
	WritebackFileData *data = g_new (WritebackFileData, 1);

	priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (self);

	uri = g_file_get_uri (file);
	g_debug ("Performing write-back for '%s'", uri);

	g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sasaas)"));

	g_variant_builder_add (&builder, "s", uri);

	g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
	for (i = 0; rdf_types[i] != NULL; i++) {
		g_variant_builder_add (&builder, "s", rdf_types[i]);
	}
	g_variant_builder_close (&builder);

	g_variant_builder_open (&builder, G_VARIANT_TYPE ("aas"));

	for (i = 0; i< results->len; i++) {
		GStrv row = g_ptr_array_index (results, i);
		guint y;

		g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
		for (y = 0; row[y] != NULL; y++) {
			g_variant_builder_add (&builder, "s", row[y]);
		}

		g_variant_builder_close (&builder);
	}

	g_variant_builder_close (&builder);

	data->retries = 0;
	data->retry_timeout = 0;
	data->self = self;
	g_object_weak_ref (G_OBJECT (data->self), self_weak_notify, data);
	data->fs = g_object_ref (fs);
	data->file = g_object_ref (file);
	data->results = g_ptr_array_ref (results);
	data->rdf_types = g_strdupv (rdf_types);
	data->cancellable = g_object_ref (cancellable);
	data->cancel_id = g_cancellable_connect (data->cancellable,
	                                         G_CALLBACK (writeback_cancel_remote_operation),
	                                         data, NULL);

	g_dbus_connection_call (priv->d_connection,
	                        TRACKER_WRITEBACK_SERVICE,
	                        TRACKER_WRITEBACK_PATH,
	                        TRACKER_WRITEBACK_INTERFACE,
	                        "PerformWriteback",
	                        g_variant_builder_end (&builder),
	                        NULL,
	                        G_DBUS_CALL_FLAGS_NONE,
	                        -1,
	                        cancellable,
	                        (GAsyncReadyCallback) writeback_file_finished,
	                        data);

	g_free (uri);

	return TRUE;
}
示例#22
0
/* TODO: Add a man page. */
gboolean
ostree_builtin_create_usb (int            argc,
                           char         **argv,
                           OstreeCommandInvocation *invocation,
                           GCancellable  *cancellable,
                           GError       **error)
{
  g_autoptr(GOptionContext) context = NULL;
  g_autoptr(OstreeAsyncProgress) progress = NULL;
  g_auto(GLnxConsoleRef) console = { 0, };

  context = g_option_context_new ("MOUNT-PATH COLLECTION-ID REF [COLLECTION-ID REF...]");

  /* Parse options. */
  g_autoptr(OstreeRepo) src_repo = NULL;

  if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &src_repo, cancellable, error))
    return FALSE;

  if (argc < 2)
    {
      ot_util_usage_error (context, "A MOUNT-PATH must be specified", error);
      return FALSE;
    }

  if (argc < 4)
    {
      ot_util_usage_error (context, "At least one COLLECTION-ID REF pair must be specified", error);
      return FALSE;
    }

  if (argc % 2 == 1)
    {
      ot_util_usage_error (context, "Only complete COLLECTION-ID REF pairs may be specified", error);
      return FALSE;
    }

  /* Open the USB stick, which must exist. Allow automounting and following symlinks. */
  const char *mount_root_path = argv[1];
  struct stat mount_root_stbuf;

  glnx_autofd int mount_root_dfd = -1;
  if (!glnx_opendirat (AT_FDCWD, mount_root_path, TRUE, &mount_root_dfd, error))
    return FALSE;
  if (!glnx_fstat (mount_root_dfd, &mount_root_stbuf, error))
    return FALSE;

  /* Read in the refs to add to the USB stick. */
  g_autoptr(GPtrArray) refs = g_ptr_array_new_full (argc, (GDestroyNotify) ostree_collection_ref_free);

  for (gsize i = 2; i < argc; i += 2)
    {
      if (!ostree_validate_collection_id (argv[i], error) ||
          !ostree_validate_rev (argv[i + 1], error))
        return FALSE;

      g_ptr_array_add (refs, ostree_collection_ref_new (argv[i], argv[i + 1]));
    }

  /* Open the destination repository on the USB stick or create it if it doesn’t exist.
   * Check it’s below @mount_root_path, and that it’s not the same as the source
   * repository.
   *
   * If the destination file system supports xattrs (for example, ext4), we use
   * a BARE_USER repository; if it doesn’t (for example, FAT), we use ARCHIVE.
   * In either case, we want a lossless repository. */
  const char *dest_repo_path = (opt_destination_repo != NULL) ? opt_destination_repo : ".ostree/repo";

  if (!glnx_shutil_mkdir_p_at (mount_root_dfd, dest_repo_path, 0755, cancellable, error))
    return FALSE;

  OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER;

  if (TEMP_FAILURE_RETRY (fgetxattr (mount_root_dfd, "user.test", NULL, 0)) < 0 &&
      (errno == ENOTSUP || errno == EOPNOTSUPP))
    mode = OSTREE_REPO_MODE_ARCHIVE;

  g_debug ("%s: Creating repository in mode %u", G_STRFUNC, mode);

  g_autoptr(OstreeRepo) dest_repo = ostree_repo_create_at (mount_root_dfd, dest_repo_path,
                                                           mode, NULL, cancellable, error);

  if (dest_repo == NULL)
    return FALSE;

  struct stat dest_repo_stbuf;

  if (!glnx_fstat (ostree_repo_get_dfd (dest_repo), &dest_repo_stbuf, error))
    return FALSE;

  if (dest_repo_stbuf.st_dev != mount_root_stbuf.st_dev)
    {
      ot_util_usage_error (context, "--destination-repo must be a descendent of MOUNT-PATH", error);
      return FALSE;
    }

  if (ostree_repo_equal (src_repo, dest_repo))
    {
      ot_util_usage_error (context, "--destination-repo must not be the source repository", error);
      return FALSE;
    }

  if (!ostree_ensure_repo_writable (dest_repo, error))
    return FALSE;

  if (opt_disable_fsync)
    ostree_repo_set_disable_fsync (dest_repo, TRUE);

  /* Copy across all of the collection–refs to the destination repo. */
  GVariantBuilder refs_builder;
  g_variant_builder_init (&refs_builder, G_VARIANT_TYPE ("a(sss)"));

  for (gsize i = 0; i < refs->len; i++)
    {
      const OstreeCollectionRef *ref = g_ptr_array_index (refs, i);

      g_variant_builder_add (&refs_builder, "(sss)",
                             ref->collection_id, ref->ref_name, "");
    }

  {
    GVariantBuilder builder;
    g_autoptr(GVariant) opts = NULL;
    OstreeRepoPullFlags flags = OSTREE_REPO_PULL_FLAGS_MIRROR;

    glnx_console_lock (&console);

    if (console.is_tty)
      progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);

    g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

    g_variant_builder_add (&builder, "{s@v}", "collection-refs",
                           g_variant_new_variant (g_variant_builder_end (&refs_builder)));
    g_variant_builder_add (&builder, "{s@v}", "flags",
                           g_variant_new_variant (g_variant_new_int32 (flags)));
    g_variant_builder_add (&builder, "{s@v}", "depth",
                           g_variant_new_variant (g_variant_new_int32 (0)));
    opts = g_variant_ref_sink (g_variant_builder_end (&builder));

    g_autofree char *src_repo_uri = g_file_get_uri (ostree_repo_get_path (src_repo));

    if (!ostree_repo_pull_with_options (dest_repo, src_repo_uri,
                                        opts,
                                        progress,
                                        cancellable, error))
      {
        ostree_repo_abort_transaction (dest_repo, cancellable, NULL);
        return FALSE;
      }

    if (progress != NULL)
      ostree_async_progress_finish (progress);
  }

  /* Ensure a summary file is present to make it easier to look up commit checksums. */
  /* FIXME: It should be possible to work without this, but find_remotes_cb() in
   * ostree-repo-pull.c currently assumes a summary file (signed or unsigned) is
   * present. */
  struct stat stbuf;
  if (!glnx_fstatat_allow_noent (ostree_repo_get_dfd (dest_repo), "summary", &stbuf, 0, error))
    return FALSE;
  if (errno == ENOENT &&
      !ostree_repo_regenerate_summary (dest_repo, NULL, cancellable, error))
    return FALSE;

  /* Add the symlinks .ostree/repos.d/@symlink_name → @dest_repo_path, unless
   * the @dest_repo_path is a well-known one like ostree/repo, in which case no
   * symlink is necessary; #OstreeRepoFinderMount always looks there. */
  if (!g_str_equal (dest_repo_path, "ostree/repo") &&
      !g_str_equal (dest_repo_path, ".ostree/repo"))
    {
      if (!glnx_shutil_mkdir_p_at (mount_root_dfd, ".ostree/repos.d", 0755, cancellable, error))
        return FALSE;

      /* Find a unique name for the symlink. If a symlink already targets
       * @dest_repo_path, use that and don’t create a new one. */
      GLnxDirFdIterator repos_iter;
      gboolean need_symlink = TRUE;

      if (!glnx_dirfd_iterator_init_at (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_iter, error))
        return FALSE;

      while (TRUE)
        {
          struct dirent *repo_dent;

          if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, error))
            return FALSE;

          if (repo_dent == NULL)
            break;

          /* Does the symlink already point to this repository? (Or is the
           * repository itself present in repos.d?) We already guarantee that
           * they’re on the same device. */
          if (repo_dent->d_ino == dest_repo_stbuf.st_ino)
            {
              need_symlink = FALSE;
              break;
            }
        }

      /* If we need a symlink, find a unique name for it and create it. */
      if (need_symlink)
        {
          /* Relative to .ostree/repos.d. */
          g_autofree char *relative_dest_repo_path = g_build_filename ("..", "..", dest_repo_path, NULL);
          guint i;
          const guint max_attempts = 100;

          for (i = 0; i < max_attempts; i++)
            {
              g_autofree char *symlink_path = g_strdup_printf (".ostree/repos.d/%02u-generated", i);

              int ret = TEMP_FAILURE_RETRY (symlinkat (relative_dest_repo_path, mount_root_dfd, symlink_path));
              if (ret < 0 && errno != EEXIST)
                return glnx_throw_errno_prefix (error, "symlinkat(%s → %s)", symlink_path, relative_dest_repo_path);
              else if (ret >= 0)
                break;
            }

          if (i == max_attempts)
            return glnx_throw (error, "Could not find an unused symlink name for the repository");
        }
    }

  /* Report success to the user. */
  g_autofree char *src_repo_path = g_file_get_path (ostree_repo_get_path (src_repo));

  g_print ("Copied %u/%u refs successfully from ‘%s’ to ‘%s’ repository in ‘%s’.\n", refs->len, refs->len,
           src_repo_path, dest_repo_path, mount_root_path);

  return TRUE;
}
示例#23
0
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
		const struct sr_channel_group *cg)
{
	struct sr_channel *ch;
	GVariant *gvar;
	GVariantBuilder gvb;

	if (key == SR_CONF_SCAN_OPTIONS) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
		return SR_OK;
	}

	if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
				drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
		return SR_OK;
	}

	if (!sdi)
		return SR_ERR_ARG;

	if (!cg) {
		switch (key) {
		case SR_CONF_DEVICE_OPTIONS:
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
			break;
		case SR_CONF_SAMPLERATE:
			g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
			gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
					ARRAY_SIZE(samplerates), sizeof(uint64_t));
			g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
			*data = g_variant_builder_end(&gvb);
			break;
		default:
			return SR_ERR_NA;
		}
	} else {
		ch = cg->channels->data;
		switch (key) {
		case SR_CONF_DEVICE_OPTIONS:
			if (ch->type == SR_CHANNEL_LOGIC)
				*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
						devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
						sizeof(uint32_t));
			else if (ch->type == SR_CHANNEL_ANALOG) {
				if (strcmp(cg->name, "Analog") == 0)
					*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
							devopts_cg_analog_group, ARRAY_SIZE(devopts_cg_analog_group),
							sizeof(uint32_t));
				else
					*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
							devopts_cg_analog_channel, ARRAY_SIZE(devopts_cg_analog_channel),
							sizeof(uint32_t));
			}
			else
				return SR_ERR_BUG;
			break;
		case SR_CONF_PATTERN_MODE:
			/* The analog group (with all 4 channels) shall not have a pattern property. */
			if (strcmp(cg->name, "Analog") == 0)
				return SR_ERR_NA;

			if (ch->type == SR_CHANNEL_LOGIC)
				*data = g_variant_new_strv(logic_pattern_str,
						ARRAY_SIZE(logic_pattern_str));
			else if (ch->type == SR_CHANNEL_ANALOG)
				*data = g_variant_new_strv(analog_pattern_str,
						ARRAY_SIZE(analog_pattern_str));
			else
				return SR_ERR_BUG;
			break;
		default:
			return SR_ERR_NA;
		}
	}

	return SR_OK;
}
示例#24
0
gboolean
ostree_builtin_pull_local (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GOptionContext) context = NULL;
  g_autoptr(OstreeRepo) repo = NULL;
  int i;
  const char *src_repo_arg;
  g_autofree char *src_repo_uri = NULL;
  g_autoptr(OstreeAsyncProgress) progress = NULL;
  g_autoptr(GPtrArray) refs_to_fetch = NULL;
  OstreeRepoPullFlags pullflags = 0;

  context = g_option_context_new ("SRC_REPO [REFS...]");

  if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
    goto out;

  if (!ostree_ensure_repo_writable (repo, error))
    goto out;

  if (argc < 2)
    {
      gchar *help = g_option_context_get_help (context, TRUE, NULL);
      g_printerr ("%s\n", help);
      g_free (help);
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "DESTINATION must be specified");
      goto out;
    }

  src_repo_arg = argv[1];

  if (src_repo_arg[0] == '/')
    src_repo_uri = g_strconcat ("file://", src_repo_arg, NULL);
  else
    { 
      g_autofree char *cwd = g_get_current_dir ();
      src_repo_uri = g_strconcat ("file://", cwd, "/", src_repo_arg, NULL);
    }

  if (opt_untrusted)
    pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED;
  if (opt_bareuseronly_files)
    pullflags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES;

  if (opt_disable_fsync)
    ostree_repo_set_disable_fsync (repo, TRUE);

  if (argc == 2)
    {
      g_autoptr(GFile) src_repo_path = g_file_new_for_path (src_repo_arg);
      g_autoptr(OstreeRepo) src_repo = ostree_repo_new (src_repo_path);
      g_autoptr(GHashTable) refs_to_clone = NULL;

      refs_to_fetch = g_ptr_array_new_with_free_func (g_free);

      if (!ostree_repo_open (src_repo, cancellable, error))
        goto out;

      /* FIXME: This should grow support for pulling refs from refs/mirrors on
       * a local repository, using ostree_repo_list_collection_refs(). */
      if (!ostree_repo_list_refs (src_repo, NULL, &refs_to_clone,
                                  cancellable, error))
        goto out;

      { GHashTableIter hashiter;
        gpointer hkey, hvalue;
        
        g_hash_table_iter_init (&hashiter, refs_to_clone);
        while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
          g_ptr_array_add (refs_to_fetch, g_strdup (hkey));
      }
      g_ptr_array_add (refs_to_fetch, NULL);
    }
  else
    {
      refs_to_fetch = g_ptr_array_new ();
      for (i = 2; i < argc; i++)
        {
          const char *ref = argv[i];
          
          g_ptr_array_add (refs_to_fetch, (char*)ref);
        }
      g_ptr_array_add (refs_to_fetch, NULL);
    }

  { GVariantBuilder builder;
    g_autoptr(GVariant) opts = NULL;
    g_auto(GLnxConsoleRef) console = { 0, };

    glnx_console_lock (&console);

    g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

    g_variant_builder_add (&builder, "{s@v}", "flags",
                           g_variant_new_variant (g_variant_new_int32 (pullflags)));
    g_variant_builder_add (&builder, "{s@v}", "refs",
                           g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch->pdata, -1)));
    if (opt_remote)
      g_variant_builder_add (&builder, "{s@v}", "override-remote-name",
                             g_variant_new_variant (g_variant_new_string (opt_remote)));
    g_variant_builder_add (&builder, "{s@v}", "require-static-deltas",
                           g_variant_new_variant (g_variant_new_boolean (opt_require_static_deltas)));
    if (opt_gpg_verify)
      g_variant_builder_add (&builder, "{s@v}", "gpg-verify",
                             g_variant_new_variant (g_variant_new_boolean (TRUE)));
    if (opt_gpg_verify_summary)
      g_variant_builder_add (&builder, "{s@v}", "gpg-verify-summary",
                             g_variant_new_variant (g_variant_new_boolean (TRUE)));
    g_variant_builder_add (&builder, "{s@v}", "depth",
                           g_variant_new_variant (g_variant_new_int32 (opt_depth)));

    if (console.is_tty)
      progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
    else
      progress = ostree_async_progress_new_and_connect (noninteractive_console_progress_changed, &console);

    opts = g_variant_ref_sink (g_variant_builder_end (&builder));
    if (!ostree_repo_pull_with_options (repo, src_repo_uri, 
                                        opts,
                                        progress,
                                        cancellable, error))
      goto out;

    if (!console.is_tty)
      {
        g_assert (progress);
        const char *status = ostree_async_progress_get_status (progress);
        if (status)
          g_print ("%s\n", status);
      }
    ostree_async_progress_finish (progress);
  }

  ret = TRUE;
 out:
  if (repo)
    ostree_repo_abort_transaction (repo, cancellable, NULL);
  return ret;
}
示例#25
0
int
main (int argc, char *argv[])
{
  gint ret;
  dev_t block_device;
  StoragedClient *client;
  GError *error;
  struct stat statbuf;
  StoragedObject *object;
  StoragedFilesystem *filesystem;
  GVariantBuilder builder;

  ret = 1;
  client = NULL;
  object = NULL;

  if (argc < 2 || strlen (argv[1]) == 0)
    {
      g_printerr ("%s: this program is only supposed to be invoked by umount(8).\n", argv[0]);
      goto out;
    }

  if (stat (argv[1], &statbuf) < 0)
    {
      g_printerr ("%s: error calling stat on %s: %m\n", argv[0], argv[1]);
      goto out;
    }

  if (S_ISBLK (statbuf.st_mode))
    block_device = statbuf.st_rdev;
  else
    block_device = statbuf.st_dev;

  error = NULL;
  client = storaged_client_new_sync (NULL, /* GCancellable */
                                   &error);
  if (client == NULL)
    {
      g_printerr ("Error connecting to the storaged daemon: %s\n", error->message);
      g_error_free (error);
      goto out;
    }

  object = lookup_object_for_block (client, block_device);
  if (object == NULL)
    {
      g_printerr ("Error finding object for block device %u:%u\n", major (block_device), minor (block_device));
      goto out;
    }

  filesystem = storaged_object_peek_filesystem (object);
  if (filesystem == NULL)
    {
      g_printerr ("Block device %u:%u is not a mountable filesystem.\n", major (block_device), minor (block_device));
      goto out;
    }

  error = NULL;
  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
  if (!storaged_filesystem_call_unmount_sync (filesystem,
                                              g_variant_builder_end (&builder), /* options */
                                              NULL, /* GCancellable */
                                              &error))
    {
      g_printerr ("Error unmounting block device %u:%u: %s\n", major (block_device), minor (block_device), error->message);
      g_error_free (error);
      goto out;
    }

  ret = 0;

 out:
  if (object != NULL)
    g_object_unref (object);
  if (client != NULL)
    g_object_unref (client);
  return ret;
}
void AbstractDBusInterface::handleMyMethodCall(GDBusConnection       *connection,
							 const gchar           *sender,
							 const gchar           *object_path,
							 const gchar           *interface_name,
							 const gchar           *method_name,
							 GVariant              *parameters,
							 GDBusMethodInvocation *invocation,
							 gpointer               user_data)
{

	std::string method = method_name;
	AbstractDBusInterface* iface = static_cast<AbstractDBusInterface*>(user_data);

	if(DebugOut::getDebugThreshhold() >= 6)
	{
		DebugOut(6)<<"DBus method call from: "<<sender<< " pid: " <<getPid(sender)<< " interface: "<<interface_name<<" method: "<<method<<endl;
		DebugOut(6)<<"DBus method call path: "<<object_path<<endl;
	}

	g_assert(iface);

	if(std::string(interface_name) == "org.freedesktop.DBus.Properties")
	{
		if(method == "Get")
		{
			gchar* propertyName = nullptr;
			gchar* ifaceName = nullptr;
			g_variant_get(parameters, "(ss)", &ifaceName, &propertyName);

			DebugOut(6) << "Parameter signature: " << g_variant_get_type_string(parameters) << endl;
//			DebugOut(6) << "Get property " << propertyName << " for interface " << ifaceName << endl;

			GError* error = nullptr;
			auto value = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, propertyName, &error, iface);
			amb::make_super(error);

			if(!value)
			{
				g_dbus_method_invocation_return_dbus_error(invocation, std::string(std::string(ifaceName)+".PropertyNotFound").c_str(), "Property not found in interface");
			}

			g_dbus_method_invocation_return_value(invocation, g_variant_new("(v)", value));
			return;
		}
		else if(method == "GetAll")
		{
			gchar* ifaceName = nullptr;
			g_variant_get(parameters, "(s)", &ifaceName);

			GVariantBuilder builder;
			g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));

			auto propertyMap = iface->getProperties();

			for(auto itr : propertyMap)
			{
				auto prop = itr.second;
				GError* error = nullptr;
				auto value = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, prop->name().c_str(), &error, iface);
				amb::make_super(error);
				g_variant_builder_add(&builder, "{sv}", prop->name().c_str(), g_variant_new("v", value));
				//sequence
				auto sequence = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, std::string(prop->name()+"Sequence").c_str(), &error, iface);
				g_variant_builder_add(&builder, "{sv}", std::string(prop->name()+"Sequence").c_str(), g_variant_new("v", sequence));

				auto quality = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, std::string(prop->name()+"ValueQuality").c_str(), &error, iface);
				g_variant_builder_add(&builder, "{sv}", std::string(prop->name()+"ValueQuality").c_str(), g_variant_new("v", quality));

				auto freq = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, std::string(prop->name()+"UpdateFrequency").c_str(), &error, iface);
				g_variant_builder_add(&builder, "{sv}", std::string(prop->name()+"UpdateFrequency").c_str(), g_variant_new("v", freq));
			}

			auto time = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, "Time", nullptr, iface);
			auto zone = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, "Zone", nullptr, iface);
			g_variant_builder_add(&builder, "{sv}", "Time", g_variant_new("v", time));
			g_variant_builder_add(&builder, "{sv}", "Zone", g_variant_new("v", zone));

			g_dbus_method_invocation_return_value(invocation, g_variant_new("(a{sv})", &builder));
			return;
		}
		else if(method == "Set")
		{
			gchar* ifaceName = nullptr;
			gchar* propName = nullptr;
			GVariant* value;
			g_variant_get(parameters, "(ssv)", &ifaceName, &propName, &value);

			AbstractDBusInterface::setProperty(connection, sender, object_path, ifaceName, propName, value, nullptr, iface,
											   [&invocation, &ifaceName](bool success, AsyncPropertyReply::Error error) {
				if(success)
				{
					g_dbus_method_invocation_return_value(invocation, nullptr);
				}
				else
				{
					g_dbus_method_invocation_return_dbus_error(invocation, ifaceName, AsyncPropertyReply::errorToStr(error).c_str());
				}
			});
			return;
		}
	}
	else if(method == "GetHistory")
	{
		double beginTime = 0;
		double endTime = 0;

		g_variant_get(parameters, "(dd)", &beginTime, &endTime);

		auto propertyMap = iface->getProperties();

		PropertyList propertyList;

		for(auto itr = propertyMap.begin(); itr != propertyMap.end(); itr++)
		{
			VariantType* prop = (*itr).second;

			if(!contains(propertyList, prop->ambPropertyName()))
				propertyList.push_back(prop->ambPropertyName());
		}

		std::string ifaceName = iface->interfaceName();

		AsyncRangePropertyRequest request;

		request.properties = propertyList;
		request.timeBegin = beginTime;
		request.timeEnd = endTime;
		request.zone = iface->zone();
		//request.sourceUuid = iface->source();

		request.completed = [&invocation,&ifaceName](AsyncRangePropertyReply* r)
		{
			auto reply = amb::make_unique(r);
			if(!reply->success)
			{
				stringstream str;
				str<<"Error during request: "<<AsyncPropertyReply::errorToStr(reply->error);
				ifaceName += ".Error";
				g_dbus_method_invocation_return_dbus_error(invocation, ifaceName.c_str(), str.str().c_str());
				return;
			}

			if(!reply->values.size())
			{
				ifaceName += ".Error";
				g_dbus_method_invocation_return_dbus_error(invocation, ifaceName.c_str(), "No results");
				return;
			}

			GVariantBuilder builder;
			g_variant_builder_init(&builder, G_VARIANT_TYPE("a{svd}"));


			for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
			{
				AbstractPropertyType* value = *itr;

				g_variant_builder_add(&builder, "{svd}", value->name.c_str(), g_variant_ref(value->toVariant()),value->timestamp);
			}

			g_dbus_method_invocation_return_value(invocation,g_variant_new("(a{svd})",&builder));
		};

		iface->re->getRangePropertyAsync(request);

		return;
	}

	g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
}
示例#27
0
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
                       const struct sr_channel_group *cg)
{
    GVariant *tuple, *rational[2];
    GVariantBuilder gvb;
    unsigned int i;
    struct dev_context *devc = NULL;

    if (key == SR_CONF_SCAN_OPTIONS) {
        *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
                                          scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
        return SR_OK;
    } else if (key == SR_CONF_DEVICE_OPTIONS && !cg) {
        *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
                                          devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
        return SR_OK;
    }

    /* Every other option requires a valid device instance. */
    if (!sdi || !(devc = sdi->priv))
        return SR_ERR_ARG;

    /* If a channel group is specified, it must be a valid one. */
    if (cg && !g_slist_find(sdi->channel_groups, cg)) {
        sr_err("Invalid channel group specified.");
        return SR_ERR;
    }

    switch (key) {
    case SR_CONF_DEVICE_OPTIONS:
        if (!cg) {
            sr_err("No channel group specified.");
            return SR_ERR_CHANNEL_GROUP;
        }
        if (cg == devc->digital_group) {
            *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
                                              NULL, 0, sizeof(uint32_t));
            return SR_OK;
        } else {
            for (i = 0; i < devc->model->analog_channels; i++) {
                if (cg == devc->analog_groups[i]) {
                    *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
                                                      analog_devopts, ARRAY_SIZE(analog_devopts), sizeof(uint32_t));
                    return SR_OK;
                }
            }
            return SR_ERR_NA;
        }
        break;
    case SR_CONF_COUPLING:
        if (!cg) {
            sr_err("No channel group specified.");
            return SR_ERR_CHANNEL_GROUP;
        }
        *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
        break;
    case SR_CONF_VDIV:
        if (!devc)
            /* Can't know this until we have the exact model. */
            return SR_ERR_ARG;
        if (!cg) {
            sr_err("No channel group specified.");
            return SR_ERR_CHANNEL_GROUP;
        }
        g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
        for (i = 0; i < devc->num_vdivs; i++) {
            rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
            rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
            tuple = g_variant_new_tuple(rational, 2);
            g_variant_builder_add_value(&gvb, tuple);
        }
        *data = g_variant_builder_end(&gvb);
        break;
    case SR_CONF_TIMEBASE:
        if (!devc)
            /* Can't know this until we have the exact model. */
            return SR_ERR_ARG;
        if (devc->num_timebases <= 0)
            return SR_ERR_NA;
        g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
        for (i = 0; i < devc->num_timebases; i++) {
            rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
            rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
            tuple = g_variant_new_tuple(rational, 2);
            g_variant_builder_add_value(&gvb, tuple);
        }
        *data = g_variant_builder_end(&gvb);
        break;
    case SR_CONF_TRIGGER_SOURCE:
        if (!devc)
            /* Can't know this until we have the exact model. */
            return SR_ERR_ARG;
        *data = g_variant_new_strv(trigger_sources,
                                   devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
        break;
    case SR_CONF_TRIGGER_SLOPE:
        *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
        break;
    case SR_CONF_DATA_SOURCE:
        if (!devc)
            /* Can't know this until we have the exact model. */
            return SR_ERR_ARG;
        switch (devc->model->series->protocol) {
        case PROTOCOL_V1:
            *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
            break;
        case PROTOCOL_V2:
            *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
            break;
        default:
            *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
            break;
        }
        break;
    default:
        return SR_ERR_NA;
    }

    return SR_OK;
}
GVariant* js_to_dbus(JSContextRef ctx,
                     const JSValueRef jsvalue,
                     const GVariantType* sig,
                     JSValueRef *exception)
{
    if (g_variant_type_is_array(sig)) {
        GVariantBuilder builder;
        g_variant_builder_init(&builder, sig);
        JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx,
                (JSObjectRef)jsvalue);

        const GVariantType* child_sig = g_variant_type_element(sig);

        if (g_variant_type_is_dict_entry(child_sig)) {
            const GVariantType* key_sig = g_variant_type_first(child_sig);
            const GVariantType* value_sig = g_variant_type_next(key_sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_function_child(ctx, jsvalue, i)) {
                    continue;
                }

                g_variant_builder_open(&builder, child_sig);
                JSValueRef key = JSValueMakeString(ctx,
                        JSPropertyNameArrayGetNameAtIndex(array, i));
                JSValueRef value = JSObjectGetPropertyAtIndex(ctx,
                        (JSObjectRef)jsvalue, i, NULL);
                g_variant_builder_add_value(&builder,
                        js_to_dbus(ctx, key, key_sig, exception));
                g_variant_builder_add_value(&builder,
                        js_to_dbus(ctx, value, value_sig, exception));
                g_variant_builder_close(&builder);
            }
            return g_variant_builder_end(&builder);

        } else {
            GVariantBuilder builder;
            g_variant_builder_init(&builder, sig);
            JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx,
                    (JSObjectRef)jsvalue);
            const GVariantType* child_sig = g_variant_type_element(sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_array_child(ctx, array, i)) {
                    continue;
                }
                g_variant_builder_add_value(&builder,
                    js_to_dbus(ctx,
                        JSObjectGetPropertyAtIndex(ctx,
                                                   (JSObjectRef)jsvalue, i,
                                                   NULL),
                        child_sig, exception));
            }
            JSPropertyNameArrayRelease(array);
            return g_variant_builder_end(&builder);
        }
    } else if (g_variant_type_is_tuple(sig)) {
        GVariantBuilder builder;
        g_variant_builder_init(&builder, sig);
        JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx,
                (JSObjectRef)jsvalue);
        const GVariantType* current_sig = g_variant_type_first(sig);
        for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
            if (filter_array_child(ctx, array, i)) {
                continue;
            }
            g_variant_builder_add_value(&builder,
                js_to_dbus(ctx,
                    JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i,
                                               NULL),
                    current_sig, exception));
            current_sig = g_variant_type_next(current_sig);
        }
        JSPropertyNameArrayRelease(array);
        return g_variant_builder_end(&builder);
    } else {
        switch (g_variant_type_peek_string(sig)[0]) {
            case 'y':
                return g_variant_new_byte(JSValueToNumber(ctx, jsvalue,
                                                          exception));
            case 'n':
                return g_variant_new_int16(JSValueToNumber(ctx, jsvalue,
                                                           exception));
            case 'q':
                return g_variant_new_uint16(JSValueToNumber(ctx, jsvalue,
                                                            exception));
            case 'i':
                return g_variant_new_int32(JSValueToNumber(ctx, jsvalue,
                                                           exception));
            case 'u':
                return g_variant_new_uint32(JSValueToNumber(ctx, jsvalue,
                                                            exception));
            case 'x':
                return g_variant_new_int64(JSValueToNumber(ctx, jsvalue,
                                                           exception));
            case 't':
                return g_variant_new_uint64(JSValueToNumber(ctx, jsvalue,
                                                            exception));
            case 'd':
                return g_variant_new_double(JSValueToNumber(ctx, jsvalue,
                                                            exception));
            case 'h':
                return g_variant_new_handle(JSValueToNumber(ctx, jsvalue,
                                                            exception));
            case 'b':
                return g_variant_new_boolean(JSValueToBoolean(ctx, jsvalue));

            case 's': {
                    char* v = jsvalue_to_cstr(ctx, jsvalue);
                    GVariant* r = g_variant_new_string(v);
                    g_free(v);
                    return r;
                }

            case 'v': {
                    //TODO:
                    /*g_variant_new_variant()*/
                    g_assert_not_reached();
                }
        }
    }
    g_assert_not_reached();
}