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 (); +}