在 C 中测试 GVfs 元数据支持

Testing for GVfs metadata support in C

我正在尝试为 Xfce 桌面的 Thunar 文件浏览器添加对每个目录查看设置的支持。因此,例如,如果用户选择以列表而不是图标网格的形式查看目录的内容,则会记住该目录的此设置,并将在每次查看该目录时使用。

现在 Thunar 是建立在 GLib 之上的,我们选择用来实现它的机制是使用 GFile 属性存储元数据,使用像 g_file_set_attributes_async 这样的方法来存储 名称为“metadata::thunar-view-type”的键。用户可以通过首选项对话框中的复选框打开或关闭每个目录的功能。我对 GIO 和 GLib 的了解非常有限,但我现在已经设法让这一切按预期工作(如果您有兴趣,可以查看我的合并请求 here)。

现在据我了解,我在这里使用的功能依赖于称为“GVfs 元数据”的东西,据我了解,这可能并非在所有系统上都可用。在 GVfs 元数据不可用的系统上,我想关闭此功能,特别是使首选项对话框中的复选框不敏感(即变灰)。因此,我需要编写一个函数来检测 gvfs 元数据支持是否可用,我的意思是我是否可以使用 g_file_set_attributes_async 之类的函数来成功保存元数据,以便将来可用。

Thunar 是用 C 写的,所以这个函数需要用 C 写,使用 C API 用于 GLib、GIO 等。 我想出的功能(通过大量阅读 API 文档、修改我发现的代码片段和实验)如下。

gboolean
thunar_g_vfs_metadata_is_supported  (void)
{
  GDBusMessage     *send, *reply;
  GDBusConnection  *conn;
  GVariant         *v1, *v2;
  GError           *error = NULL;
  const gchar     **service_names;
  gboolean          metadata_found;

  /* connect to the session bus */
  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);

  /* check that the connection was opened sucessfully */
  if (error != NULL)
    {
      g_error_free (error);
      return FALSE;
    }

  /* create the message to send to list the available services */
  send = g_dbus_message_new_method_call ("org.freedesktop.DBus",
                                         "/org/freedesktop/DBus",
                                         "org.freedesktop.DBus",
                                         "ListNames");

  /* send the message and wait for the reply */
  reply = g_dbus_connection_send_message_with_reply_sync (conn, send, G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                          -1, NULL, NULL, &error);

  /* release the connection and the sent message */
  g_object_unref (send);
  g_object_unref (conn);

  /* check if we got a sucessful reply */
  if (error != NULL)
    {
      g_error_free (error);
      return FALSE;
    }

  /* extract the GVariant with the array of strings describing the available services */
  v1 = g_dbus_message_get_body (reply); /* v1 belongs to reply and must not be freed */
  if (v1 == NULL || !g_variant_is_container (v1) || g_variant_n_children (v1) < 1)
    {
      g_object_unref (reply);
      return FALSE;
    }
  v2 = g_variant_get_child_value (v1, 0);
  g_object_unref (reply);

  /* check that the GVariant we have been given does contain an array of strings */
  if (!g_variant_is_of_type (v2, G_VARIANT_TYPE_STRING_ARRAY))
    {
      g_variant_unref (v2);
      return FALSE;
    }

  /* search through the list of service names to see if gvfs metadata is present */
  metadata_found = FALSE;
  service_names = g_variant_get_strv (v2, NULL);
  for (int i=0; service_names[i] != NULL; i++)
    if (g_strcmp0 (service_names[i], "org.gtk.vfs.Metadata") == 0)
      metadata_found = TRUE;

  g_free (service_names);
  g_variant_unref (v2);

  return metadata_found;
}

如您所见,该函数使用DBus查询服务名称,以查看是否有必要的服务可用。现在,就我能够测试的而言,这个函数可以正常工作。然而,在代码审查期间,有人质疑是否可以在不依赖 DBus 的情况下完成此操作(即使 GVfs 元数据可用,DBus 本身也可能不可用)。

因此(终于!)我的问题是:通过 C API 为 GLib、GIO 测试 GVfs 元数据支持的最佳(即最稳健和准确)方法是什么,等等?。正如我上面所说,“GVfs 元数据支持”是指“我可以使用 g_file_set_attributes_async 之类的函数来成功保存元数据,以便将来可用吗?”。

我考虑过的一种方法是查看 运行 个名为“gvfsd-metadata”的进程列表,但这对我来说似乎有点笨拙。

此外,如上所述,我是这些技术的新手,所以我绝对有可能误解了这里的内容,所以如果您发现我在上面所做的断言中有任何错误,请告诉我.

谢谢!

(是的,平常的故事,我很长一段时间 reader SO&co,但第一次提问,所以请随时编辑或让我知道我是否做了什么wrong/bad)

致电g_file_query_settable_attributes() and g_file_query_writable_namespaces() on the GFile, as described in the GFileInfo documentation:

However, not all attributes can be changed in the file. For instance, the actual size of a file cannot be changed via g_file_info_set_size(). You may call g_file_query_settable_attributes() and g_file_query_writable_namespaces() to discover the settable attributes of a particular file at runtime.