diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build
index b6ce1788f..35f0ba552 100644
--- a/docs/reference/gio/meson.build
+++ b/docs/reference/gio/meson.build
@@ -68,6 +68,7 @@ if get_option('gtk_doc')
'gproxyresolverportal.h',
'gregistrysettingsbackend.h',
'gresourcefile.h',
+ 'gsandbox.h',
'gsettingsbackendinternal.h',
'gsettings-mapping.h',
'gsettingsschema-internal.h',
diff --git a/gio/gportalsupport.c b/gio/gportalsupport.c
index dc82481b1..7d0e3226c 100644
--- a/gio/gportalsupport.c
+++ b/gio/gportalsupport.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "gportalsupport.h"
+#include "gsandbox.h"
static gboolean use_portal;
static gboolean network_available;
@@ -30,52 +31,59 @@ static void
read_flatpak_info (void)
{
static gsize flatpak_info_read = 0;
- const gchar *path = "/.flatpak-info";
+ GSandboxType sandbox_type;
if (!g_once_init_enter (&flatpak_info_read))
return;
- if (g_file_test (path, G_FILE_TEST_EXISTS))
+ sandbox_type = glib_get_sandbox_type ();
+ switch (sandbox_type)
{
- GKeyFile *keyfile;
+ case G_SANDBOX_TYPE_FLATPAK:
+ {
+ GKeyFile *keyfile;
- use_portal = TRUE;
- network_available = FALSE;
- dconf_access = FALSE;
-
- keyfile = g_key_file_new ();
- if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
- {
- char **shared = NULL;
- char *dconf_policy = NULL;
-
- shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
- if (shared)
- {
- network_available = g_strv_contains ((const char * const *)shared, "network");
- g_strfreev (shared);
- }
-
- dconf_policy = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
- if (dconf_policy)
- {
- if (strcmp (dconf_policy, "talk") == 0)
- dconf_access = TRUE;
- g_free (dconf_policy);
- }
- }
-
- g_key_file_unref (keyfile);
- }
- else
- {
- const char *var;
-
- var = g_getenv ("GTK_USE_PORTAL");
- if (var && var[0] == '1')
use_portal = TRUE;
- network_available = TRUE;
- dconf_access = TRUE;
+ network_available = FALSE;
+ dconf_access = FALSE;
+
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, "/.flatpak-info", G_KEY_FILE_NONE, NULL))
+ {
+ char **shared = NULL;
+ char *dconf_policy = NULL;
+
+ shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
+ if (shared)
+ {
+ network_available = g_strv_contains ((const char *const *) shared, "network");
+ g_strfreev (shared);
+ }
+
+ dconf_policy = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
+ if (dconf_policy)
+ {
+ if (strcmp (dconf_policy, "talk") == 0)
+ dconf_access = TRUE;
+ g_free (dconf_policy);
+ }
+ }
+
+ g_key_file_unref (keyfile);
+ }
+ break;
+ case G_SANDBOX_TYPE_UNKNOWN:
+ case G_SANDBOX_TYPE_SNAP:
+ {
+ const char *var;
+
+ var = g_getenv ("GTK_USE_PORTAL");
+ if (var && var[0] == '1')
+ use_portal = TRUE;
+ network_available = TRUE;
+ dconf_access = TRUE;
+ }
+ break;
}
g_once_init_leave (&flatpak_info_read, 1);
diff --git a/gio/gsandbox.c b/gio/gsandbox.c
new file mode 100644
index 000000000..ced0df7db
--- /dev/null
+++ b/gio/gsandbox.c
@@ -0,0 +1,75 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2022 Canonical Ltd
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see .
+ */
+
+#include "config.h"
+
+#include "gsandbox.h"
+
+static gboolean
+is_flatpak (void)
+{
+ return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+}
+
+static gboolean
+is_snap (void)
+{
+ const gchar *snap_path;
+ gchar *yaml_path;
+ gboolean result;
+
+ snap_path = g_getenv ("SNAP");
+ if (snap_path == NULL)
+ return FALSE;
+
+ yaml_path = g_build_filename (snap_path, "meta", "snap.yaml", NULL);
+ result = g_file_test (yaml_path, G_FILE_TEST_EXISTS);
+ g_free (yaml_path);
+
+ return result;
+}
+
+/*
+ * glib_get_sandbox_type:
+ *
+ * Gets the type of sandbox this process is running inside.
+ *
+ * Checking for sandboxes may involve doing blocking I/O calls, but should not take
+ * any significant time.
+ *
+ * The sandbox will not change over the lifetime of the process, so calling this
+ * function once and reusing the result is valid.
+ *
+ * If this process is not sandboxed then @G_SANDBOX_TYPE_UNKNOWN will be returned.
+ * This is because this function only detects known sandbox types in #GSandboxType.
+ * It may be updated in the future if new sandboxes come into use.
+ *
+ * Returns: a #GSandboxType.
+ */
+GSandboxType
+glib_get_sandbox_type (void)
+{
+ if (is_flatpak ())
+ return G_SANDBOX_TYPE_FLATPAK;
+ else if (is_snap ())
+ return G_SANDBOX_TYPE_SNAP;
+ else
+ return G_SANDBOX_TYPE_UNKNOWN;
+}
diff --git a/gio/gsandbox.h b/gio/gsandbox.h
new file mode 100644
index 000000000..7861b2756
--- /dev/null
+++ b/gio/gsandbox.h
@@ -0,0 +1,47 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2022 Canonical Ltd
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see .
+ */
+
+#ifndef __G_SANDBOX_H__
+#define __G_SANDBOX_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/*
+ * GSandboxType:
+ * @G_SANDBOX_TYPE_UNKNOWN: process is running inside an unknown or no sandbox.
+ * @G_SANDBOX_TYPE_FLATPAK: process is running inside a flatpak sandbox.
+ * @G_SANDBOX_TYPE_SNAP: process is running inside a snap sandbox.
+ *
+ * The type of sandbox that processes can be running inside.
+ */
+typedef enum
+{
+ G_SANDBOX_TYPE_UNKNOWN,
+ G_SANDBOX_TYPE_FLATPAK,
+ G_SANDBOX_TYPE_SNAP
+} GSandboxType;
+
+GSandboxType glib_get_sandbox_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gio/meson.build b/gio/meson.build
index a51926fcf..4fb5e9061 100644
--- a/gio/meson.build
+++ b/gio/meson.build
@@ -369,15 +369,17 @@ if host_system != 'windows'
)
portal_sources = [files(
- 'gdocumentportal.c',
- 'gopenuriportal.c',
- 'gmemorymonitorportal.c',
- 'gnetworkmonitorportal.c',
- 'gpowerprofilemonitorportal.c',
- 'gproxyresolverportal.c',
- 'gtrashportal.c',
- 'gportalsupport.c',
- 'gportalnotificationbackend.c'),
+ 'gdocumentportal.c',
+ 'gopenuriportal.c',
+ 'gmemorymonitorportal.c',
+ 'gnetworkmonitorportal.c',
+ 'gpowerprofilemonitorportal.c',
+ 'gproxyresolverportal.c',
+ 'gtrashportal.c',
+ 'gportalsupport.c',
+ 'gportalnotificationbackend.c',
+ 'gsandbox.c',
+ ),
xdp_dbus_generated
]
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 22746c97e..4faccd6f4 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -100,6 +100,9 @@ gio_tests = {
'power-profile-monitor' : {},
'proxy-test' : {},
'readwrite' : {},
+ 'sandbox' : {
+ 'source': ['sandbox.c', '../gsandbox.c'],
+ },
'simple-async-result' : {},
'simple-proxy' : {},
'sleepy-stream' : {},
diff --git a/gio/tests/sandbox.c b/gio/tests/sandbox.c
new file mode 100644
index 000000000..849260ea0
--- /dev/null
+++ b/gio/tests/sandbox.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2022 Canonical Ltd
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see .
+ */
+
+#include "../gsandbox.h"
+#include
+#include
+
+static void
+test_sandbox_none (void)
+{
+ g_assert_cmpint (glib_get_sandbox_type (), ==, G_SANDBOX_TYPE_UNKNOWN);
+}
+
+static void
+test_sandbox_snap (void)
+{
+ gchar *temp_dir, *snap_path, *snap_version_path, *meta_path, *yaml_path;
+ GError *error = NULL;
+
+ temp_dir = g_dir_make_tmp ("gio-test-sandbox_XXXXXX", &error);
+ g_assert_no_error (error);
+ snap_path = g_build_filename (temp_dir, "snap", NULL);
+ snap_version_path = g_build_filename (snap_path, "current", NULL);
+ meta_path = g_build_filename (snap_version_path, "meta", NULL);
+ yaml_path = g_build_filename (meta_path, "snap.yaml", NULL);
+ g_mkdir_with_parents (meta_path, 0700);
+ g_file_set_contents (yaml_path, "", -1, NULL);
+ g_setenv ("SNAP", snap_version_path, TRUE);
+
+ g_assert_cmpint (glib_get_sandbox_type (), ==, G_SANDBOX_TYPE_SNAP);
+
+ g_unsetenv ("SNAP");
+ g_unlink (yaml_path);
+ g_rmdir (meta_path);
+ g_rmdir (snap_version_path);
+ g_rmdir (snap_path);
+ g_rmdir (temp_dir);
+ g_free (temp_dir);
+ g_free (snap_path);
+ g_free (meta_path);
+ g_free (yaml_path);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/sandbox/none", test_sandbox_none);
+ g_test_add_func ("/sandbox/snap", test_sandbox_snap);
+
+ return g_test_run ();
+}