在 C 中测试 GVfs 元数据支持

Posted

技术标签:

【中文标题】在 C 中测试 GVfs 元数据支持【英文标题】:Testing for GVfs metadata support in C 【发布时间】:2020-10-24 04:25:09 【问题描述】:

我正在尝试向 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 语言编写,使用 GLib、GIO 等的 C API。 我想出的功能(通过大量阅读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 本身也可能不可用)。

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

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

另外,如上所述,我对这些技术非常陌生,所以我绝对有可能在这里误解了一些东西,所以如果你发现我上面的断言中有任何错误,请告诉我。

谢谢!

(是的,通常的故事,我是 SO & co 的长期读者,但第一次提问,所以请随时编辑或让我知道我是否做错/坏事)

【问题讨论】:

【参考方案1】:

GFile 上致电g_file_query_settable_attributes()g_file_query_writable_namespaces(),如the GFileInfo documentation 中所述:

但是,并非所有属性都可以在文件中更改。例如,文件的实际大小不能通过g_file_info_set_size() 更改。您可以调用g_file_query_settable_attributes()g_file_query_writable_namespaces() 在运行时发现特定文件的可设置属性。

【讨论】:

感谢您的回答!所以我在这里真正希望的是一种测试元数据支持是否可用于整个文件系统的方法,而不是测试单个文件的可用性(如果这些文件之间实际上存在差异)。但是, g_file_query_writable_namespaces() 可能是一种方法,因为我可以在根目录的 GFile 上调用它,并在返回的名称中查找“元数据”。我想这将是设置元数据是否适用于整个文件系统(?)的一个非常可靠的指标,所以感谢您向我展示这个! 跟进我之前的评论:我提到的使用根目录的方法似乎效果很好。

以上是关于在 C 中测试 GVfs 元数据支持的主要内容,如果未能解决你的问题,请参考以下文章

dompdf 支持哪些 PDF 元数据?

php 对 WEBP 图像元数据的支持

任何现代文件系统都支持任意元数据处理吗?

将图像存储在 Firebase Storage 中并将元数据保存在 Firebase Cloud Firestore(测试版)中

如何在 Android 上获取和修改元数据以支持音频文件?

数据必备知识:数据仓库之数据存储