Skip to content
Snippets Groups Projects
Commit 803d2be0 authored by Ludovico de Nittis's avatar Ludovico de Nittis :palm_tree:
Browse files

Create a new SrtContainerInfo GObject


Move the existing container information from `system-info` to a separate
GObject class. In this way it will be easier to expand the amount of
information, related to the container that is in use, that we can log.

Signed-off-by: default avatarLudovico de Nittis <ludovico.denittis@collabora.com>
parent a78b42e1
Branches
Tags
1 merge request!305Add Flatpak version information
/*<private_header>*/
/*
* Copyright © 2021 Collabora Ltd.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "steam-runtime-tools/container.h"
#include <json-glib/json-glib.h>
/*
* _srt_container_info_new:
* @type: Type of container
* @host_directory: (nullable) (type filename): Directory where host files can
* be found
*
* Inline convenience function to create a new SrtContainerInfo.
* This is not part of the public API.
*
* Returns: (transfer full): A new #SrtContainerInfo
*/
static inline SrtContainerInfo *_srt_container_info_new (SrtContainerType type,
const gchar *host_directory);
#ifndef __GTK_DOC_IGNORE__
static inline SrtContainerInfo *
_srt_container_info_new (SrtContainerType type,
const gchar *host_directory)
{
return g_object_new (SRT_TYPE_CONTAINER_INFO,
"type", type,
"host-directory", host_directory,
NULL);
}
#endif
SrtContainerInfo *_srt_check_container (int sysroot_fd,
const gchar *sysroot);
SrtContainerInfo *_srt_container_info_get_from_report (JsonObject *json_obj);
/*
* Copyright © 2021 Collabora Ltd.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "steam-runtime-tools/container.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include "steam-runtime-tools/container-internal.h"
#include "steam-runtime-tools/enums.h"
#include "steam-runtime-tools/glib-backports-internal.h"
#include "steam-runtime-tools/json-glib-backports-internal.h"
#include "steam-runtime-tools/resolve-in-sysroot-internal.h"
#include "steam-runtime-tools/utils.h"
#include "steam-runtime-tools/utils-internal.h"
/**
* SECTION:container-info
* @title: Container info
* @short_description: Information about the eventual container that is currently in use
* @include: steam-runtime-tools/steam-runtime-tools.h
*/
struct _SrtContainerInfo
{
/*< private >*/
GObject parent;
gchar *host_directory;
SrtContainerType type;
};
struct _SrtContainerInfoClass
{
/*< private >*/
GObjectClass parent_class;
};
enum {
PROP_0,
PROP_HOST_DIRECTORY,
PROP_TYPE,
N_PROPERTIES
};
G_DEFINE_TYPE (SrtContainerInfo, srt_container_info, G_TYPE_OBJECT)
static void
srt_container_info_init (SrtContainerInfo *self)
{
}
static void
srt_container_info_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SrtContainerInfo *self = SRT_CONTAINER_INFO (object);
switch (prop_id)
{
case PROP_HOST_DIRECTORY:
g_value_set_string (value, self->host_directory);
break;
case PROP_TYPE:
g_value_set_enum (value, self->type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
srt_container_info_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SrtContainerInfo *self = SRT_CONTAINER_INFO (object);
switch (prop_id)
{
case PROP_HOST_DIRECTORY:
/* Construct-only */
g_return_if_fail (self->host_directory == NULL);
self->host_directory = g_value_dup_string (value);
break;
case PROP_TYPE:
/* Construct-only */
g_return_if_fail (self->type == 0);
self->type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
srt_container_info_finalize (GObject *object)
{
SrtContainerInfo *self = SRT_CONTAINER_INFO (object);
g_free (self->host_directory);
G_OBJECT_CLASS (srt_container_info_parent_class)->finalize (object);
}
static GParamSpec *properties[N_PROPERTIES] = { NULL };
static void
srt_container_info_class_init (SrtContainerInfoClass *cls)
{
GObjectClass *object_class = G_OBJECT_CLASS (cls);
object_class->get_property = srt_container_info_get_property;
object_class->set_property = srt_container_info_set_property;
object_class->finalize = srt_container_info_finalize;
properties[PROP_HOST_DIRECTORY] =
g_param_spec_string ("host-directory", "Host directory",
"Absolute path where important files from the host "
"system can be found",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
properties[PROP_TYPE] =
g_param_spec_enum ("type", "Container type",
"Which container type is currently in use",
SRT_TYPE_CONTAINER_TYPE, SRT_CONTAINER_TYPE_UNKNOWN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
}
typedef struct
{
SrtContainerType type;
const char *name;
} ContainerTypeName;
static const ContainerTypeName container_types[] =
{
{ SRT_CONTAINER_TYPE_DOCKER, "docker" },
{ SRT_CONTAINER_TYPE_FLATPAK, "flatpak" },
{ SRT_CONTAINER_TYPE_PODMAN, "podman" },
{ SRT_CONTAINER_TYPE_PRESSURE_VESSEL, "pressure-vessel" },
};
static SrtContainerType
container_type_from_name (const char *name)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (container_types); i++)
{
const ContainerTypeName *entry = &container_types[i];
if (strcmp (entry->name, name) == 0)
return entry->type;
}
return SRT_CONTAINER_TYPE_UNKNOWN;
}
/**
* _srt_check_container:
* @sysroot_fd: Sysroot file descriptor
* @sysroot: (not nullable) (type filename): Path to the sysroot
*
* Gather and return information about the container that is currently in use.
*
* Returns: (transfer full): A new #SrtContainerInfo object.
* Free with g_object_unref().
*/
SrtContainerInfo *
_srt_check_container (int sysroot_fd,
const gchar *sysroot)
{
g_autofree gchar *contents = NULL;
g_autofree gchar *run_host_path = NULL;
g_autofree gchar *host_directory = NULL;
SrtContainerType type = SRT_CONTAINER_TYPE_UNKNOWN;
glnx_autofd int run_host_fd = -1;
g_return_val_if_fail (sysroot != NULL, NULL);
if (sysroot_fd < 0)
{
g_debug ("Cannot find container info: previously failed to open "
"sysroot %s", sysroot);
goto out;
}
g_debug ("Finding container info in sysroot %s...", sysroot);
run_host_fd = _srt_resolve_in_sysroot (sysroot_fd, "/run/host",
SRT_RESOLVE_FLAGS_DIRECTORY,
&run_host_path, NULL);
if (run_host_path != NULL)
host_directory = g_build_filename (sysroot, run_host_path, NULL);
if (_srt_file_get_contents_in_sysroot (sysroot_fd,
"/run/host/container-manager",
&contents, NULL, NULL))
{
g_strchomp (contents);
type = container_type_from_name (contents);
g_debug ("Type %d based on /run/host/container-manager", type);
goto out;
}
if (_srt_file_get_contents_in_sysroot (sysroot_fd,
"/run/systemd/container",
&contents, NULL, NULL))
{
g_strchomp (contents);
type = container_type_from_name (contents);
g_debug ("Type %d based on /run/systemd/container", type);
goto out;
}
if (_srt_file_test_in_sysroot (sysroot, sysroot_fd, "/.flatpak-info",
G_FILE_TEST_IS_REGULAR))
{
type = SRT_CONTAINER_TYPE_FLATPAK;
g_debug ("Flatpak based on /.flatpak-info");
goto out;
}
if (_srt_file_test_in_sysroot (sysroot, sysroot_fd, "/run/pressure-vessel",
G_FILE_TEST_IS_DIR))
{
type = SRT_CONTAINER_TYPE_PRESSURE_VESSEL;
g_debug ("pressure-vessel based on /run/pressure-vessel");
goto out;
}
if (_srt_file_test_in_sysroot (sysroot, sysroot_fd, "/.dockerenv",
G_FILE_TEST_EXISTS))
{
type = SRT_CONTAINER_TYPE_DOCKER;
g_debug ("Docker based on /.dockerenv");
goto out;
}
if (_srt_file_test_in_sysroot (sysroot, sysroot_fd, "/run/.containerenv",
G_FILE_TEST_EXISTS))
{
type = SRT_CONTAINER_TYPE_PODMAN;
g_debug ("Podman based on /run/.containerenv");
goto out;
}
if (_srt_file_get_contents_in_sysroot (sysroot_fd, "/proc/1/cgroup",
&contents, NULL, NULL))
{
if (strstr (contents, "/docker/") != NULL)
type = SRT_CONTAINER_TYPE_DOCKER;
if (type != SRT_CONTAINER_TYPE_UNKNOWN)
{
g_debug ("Type %d based on /proc/1/cgroup", type);
goto out;
}
g_clear_pointer (&contents, g_free);
}
if (run_host_fd >= 0)
{
g_debug ("Unknown container technology based on /run/host");
type = SRT_CONTAINER_TYPE_UNKNOWN;
goto out;
}
/* We haven't found any particular evidence of being in a container */
g_debug ("Probably not a container");
type = SRT_CONTAINER_TYPE_NONE;
out:
return _srt_container_info_new (type, host_directory);
}
/**
* srt_container_info_get_container_type:
* @self: A SrtContainerInfo object
*
* If the program appears to be running in a container, return what sort
* of container it is.
*
* Implementation of srt_system_info_get_container_type().
*
* Returns: A recognised container type, or %SRT_CONTAINER_TYPE_NONE
* if a container cannot be detected, or %SRT_CONTAINER_TYPE_UNKNOWN
* if unsure.
*/
SrtContainerType
srt_container_info_get_container_type (SrtContainerInfo *self)
{
g_return_val_if_fail (SRT_IS_CONTAINER_INFO (self), SRT_CONTAINER_TYPE_UNKNOWN);
return self->type;
}
/**
* srt_container_info_get_container_host_directory:
* @self: A SrtContainerInfo object
*
* If the program appears to be running in a container, return the
* directory where host files can be found. For example, if this function
* returns `/run/host`, it might be possible to load the host system's
* `/usr/lib/os-release` by reading `/run/host/usr/lib/os-release`.
*
* The returned directory is usually not complete. For example,
* in a Flatpak app, `/run/host` will sometimes contain the host system's
* `/etc` and `/usr`, but only if suitable permissions flags are set.
*
* Implementation of srt_system_info_dup_container_host_directory().
*
* Returns: (type filename) (nullable): A path from which at least some
* host-system files can be loaded, typically `/run/host`, or %NULL if
* unknown or unavailable.
*/
const gchar *
srt_container_info_get_container_host_directory (SrtContainerInfo *self)
{
g_return_val_if_fail (SRT_IS_CONTAINER_INFO (self), NULL);
return self->host_directory;
}
/**
* _srt_system_info_get_container_info_from_report:
* @json_obj: (not nullable): A JSON Object used to search for "container"
* property
* @host_path: (not nullable): Used to return the host path
*
* If the provided @json_obj doesn't have a "container" member,
* %SRT_CONTAINER_TYPE_UNKNOWN will be returned.
* If @json_obj has some elements that we can't parse, the returned
* #SrtContainerType will be set to %SRT_CONTAINER_TYPE_UNKNOWN.
*
* Returns: The found container type
*/
SrtContainerInfo *
_srt_container_info_get_from_report (JsonObject *json_obj)
{
JsonObject *json_sub_obj;
JsonObject *json_host_obj = NULL;
const gchar *type_string = NULL;
const gchar *host_path = NULL;
SrtContainerType type = SRT_CONTAINER_TYPE_UNKNOWN;
g_return_val_if_fail (json_obj != NULL, NULL);
if (json_object_has_member (json_obj, "container"))
{
json_sub_obj = json_object_get_object_member (json_obj, "container");
if (json_sub_obj == NULL)
goto out;
if (json_object_has_member (json_sub_obj, "type"))
{
type_string = json_object_get_string_member (json_sub_obj, "type");
G_STATIC_ASSERT (sizeof (SrtContainerType) == sizeof (gint));
if (!srt_enum_from_nick (SRT_TYPE_CONTAINER_TYPE, type_string, (gint *) &type, NULL))
{
g_debug ("The parsed container type '%s' is not a known element", type_string);
type = SRT_CONTAINER_TYPE_UNKNOWN;
}
}
if (json_object_has_member (json_sub_obj, "host"))
{
json_host_obj = json_object_get_object_member (json_sub_obj, "host");
host_path = json_object_get_string_member_with_default (json_host_obj, "path",
NULL);
}
}
out:
return _srt_container_info_new (type,
host_path);
}
/*
* Copyright © 2021 Collabora Ltd.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#if !defined(_SRT_IN_SINGLE_HEADER) && !defined(_SRT_COMPILATION)
#error "Do not include directly, use <steam-runtime-tools/steam-runtime-tools.h>"
#endif
#include <glib.h>
#include <glib-object.h>
#include <steam-runtime-tools/macros.h>
typedef struct _SrtContainerInfo SrtContainerInfo;
typedef struct _SrtContainerInfoClass SrtContainerInfoClass;
#define SRT_TYPE_CONTAINER_INFO srt_container_info_get_type ()
#define SRT_CONTAINER_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SRT_TYPE_CONTAINER_INFO, SrtContainerInfo))
#define SRT_CONTAINER_INFO_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), SRT_TYPE_CONTAINER_INFO, SrtContainerInfoClass))
#define SRT_IS_CONTAINER_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SRT_TYPE_CONTAINER_INFO))
#define SRT_IS_CONTAINER_INFO_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), SRT_TYPE_CONTAINER_INFO))
#define SRT_CONTAINER_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SRT_TYPE_CONTAINER_INFO, SrtContainerInfoClass)
_SRT_PUBLIC
GType srt_container_info_get_type (void);
/**
* SrtContainerType:
* @SRT_CONTAINER_TYPE_UNKNOWN: Unknown container type
* @SRT_CONTAINER_TYPE_NONE: No container detected
* @SRT_CONTAINER_TYPE_FLATPAK: Running in a Flatpak app
* @SRT_CONTAINER_TYPE_PRESSURE_VESSEL: Running in a Steam Runtime container
* using pressure-vessel
* @SRT_CONTAINER_TYPE_DOCKER: Running in a Docker container
* @SRT_CONTAINER_TYPE_PODMAN: Running in a Podman container
*
* A type of container.
*/
typedef enum
{
SRT_CONTAINER_TYPE_NONE = 0,
SRT_CONTAINER_TYPE_FLATPAK,
SRT_CONTAINER_TYPE_PRESSURE_VESSEL,
SRT_CONTAINER_TYPE_DOCKER,
SRT_CONTAINER_TYPE_PODMAN,
SRT_CONTAINER_TYPE_UNKNOWN = -1
} SrtContainerType;
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtContainerInfo, g_object_unref)
#endif
_SRT_PUBLIC
SrtContainerType srt_container_info_get_container_type (SrtContainerInfo *self);
_SRT_PUBLIC
const gchar *srt_container_info_get_container_host_directory (SrtContainerInfo *self);
......@@ -24,6 +24,7 @@
libsteamrt_sources = [
'architecture-internal.h',
'architecture.c',
'container.c',
'cpu-feature-internal.h',
'cpu-feature.c',
'desktop-entry-internal.h',
......@@ -69,6 +70,7 @@ libsteamrt_sources = [
libsteamrt_public_headers = [
'architecture.h',
'container.h',
'cpu-feature.h',
'desktop-entry.h',
'graphics.h',
......
......@@ -28,6 +28,7 @@
#define _SRT_IN_SINGLE_HEADER
#include <steam-runtime-tools/architecture.h>
#include <steam-runtime-tools/container.h>
#include <steam-runtime-tools/cpu-feature.h>
#include <steam-runtime-tools/desktop-entry.h>
#include <steam-runtime-tools/enums.h>
......
......@@ -32,6 +32,7 @@
#include "steam-runtime-tools/architecture.h"
#include "steam-runtime-tools/architecture-internal.h"
#include "steam-runtime-tools/container-internal.h"
#include "steam-runtime-tools/cpu-feature-internal.h"
#include "steam-runtime-tools/desktop-entry-internal.h"
#include "steam-runtime-tools/graphics.h"
......@@ -117,6 +118,7 @@ struct _SrtSystemInfo
/* If %TRUE, #SrtSystemInfo cannot be changed anymore */
gboolean immutable_values;
GHashTable *cached_hidden_deps;
SrtContainerInfo *container_info;
SrtSteam *steam_data;
SrtXdgPortal *xdg_portal_data;
struct
......@@ -164,12 +166,6 @@ struct _SrtSystemInfo
gboolean have_data;
} pinned_libs;
struct
{
SrtContainerType type;
gchar *host_directory;
gboolean have_data;
} container;
struct
{
GList *values;
gboolean have_data;
......@@ -373,8 +369,6 @@ srt_system_info_init (SrtSystemInfo *self)
_srt_os_release_init (&self->os_release);
self->container.type = SRT_CONTAINER_TYPE_UNKNOWN;
srt_system_info_set_sysroot (self, "/");
srt_system_info_set_environ (self, NULL);
}
......@@ -433,9 +427,7 @@ forget_desktop_entries (SrtSystemInfo *self)
static void
forget_container_info (SrtSystemInfo *self)
{
g_clear_pointer (&self->container.host_directory, g_free);
self->container.type = SRT_CONTAINER_TYPE_UNKNOWN;
self->container.have_data = FALSE;
g_clear_object (&self->container_info);
}
/*
......@@ -629,8 +621,6 @@ srt_system_info_new (const char *expectations)
}
static gchar ** _srt_system_info_driver_environment_from_report (JsonObject *json_obj);
static SrtContainerType _srt_system_info_get_container_info_from_report (JsonObject *json_obj,
gchar **host_path);
static gchar ** _srt_system_info_get_pinned_libs_from_report (JsonObject *json_obj,
const gchar *which,
gchar ***messages);
......@@ -857,8 +847,7 @@ srt_system_info_new_from_json (const char *path,
_srt_os_release_populate_from_report (json_obj, &info->os_release);
info->container.type = _srt_system_info_get_container_info_from_report (json_obj,
&info->container.host_directory);
info->container_info = _srt_container_info_get_from_report (json_obj);
info->cached_driver_environment = _srt_system_info_driver_environment_from_report (json_obj);
......@@ -3859,151 +3848,31 @@ _srt_system_info_driver_environment_from_report (JsonObject *json_obj)
"<invalid>");
}
typedef struct
{
SrtContainerType type;
const char *name;
} ContainerTypeName;
static const ContainerTypeName container_types[] =
{
{ SRT_CONTAINER_TYPE_DOCKER, "docker" },
{ SRT_CONTAINER_TYPE_FLATPAK, "flatpak" },
{ SRT_CONTAINER_TYPE_PODMAN, "podman" },
{ SRT_CONTAINER_TYPE_PRESSURE_VESSEL, "pressure-vessel" },
};
static SrtContainerType
container_type_from_name (const char *name)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (container_types); i++)
{
const ContainerTypeName *entry = &container_types[i];
if (strcmp (entry->name, name) == 0)
return entry->type;
}
return SRT_CONTAINER_TYPE_UNKNOWN;
}
static void
ensure_container_info (SrtSystemInfo *self)
{
g_autofree gchar *contents = NULL;
g_autofree gchar *run_host_path = NULL;
glnx_autofd int run_host_fd = -1;
if (self->container.have_data || self->immutable_values)
return;
g_assert (self->container.host_directory == NULL);
g_assert (self->container.type == SRT_CONTAINER_TYPE_UNKNOWN);
g_assert (self->sysroot != NULL);
if (self->sysroot_fd < 0)
{
g_debug ("Cannot find container info: previously failed to open "
"sysroot %s", self->sysroot);
goto out;
}
g_debug ("Finding container info in sysroot %s...", self->sysroot);
run_host_fd = _srt_resolve_in_sysroot (self->sysroot_fd, "/run/host",
SRT_RESOLVE_FLAGS_DIRECTORY,
&run_host_path, NULL);
if (run_host_path != NULL)
self->container.host_directory = g_build_filename (self->sysroot,
run_host_path,
NULL);
if (_srt_file_get_contents_in_sysroot (self->sysroot_fd,
"/run/host/container-manager",
&contents, NULL, NULL))
{
g_strchomp (contents);
self->container.type = container_type_from_name (contents);
g_debug ("Type %d based on /run/host/container-manager",
self->container.type);
goto out;
}
if (_srt_file_get_contents_in_sysroot (self->sysroot_fd,
"/run/systemd/container",
&contents, NULL, NULL))
{
g_strchomp (contents);
self->container.type = container_type_from_name (contents);
g_debug ("Type %d based on /run/systemd/container",
self->container.type);
goto out;
}
if (_srt_file_test_in_sysroot (self->sysroot, self->sysroot_fd,
"/.flatpak-info", G_FILE_TEST_IS_REGULAR))
{
self->container.type = SRT_CONTAINER_TYPE_FLATPAK;
g_debug ("Flatpak based on /.flatpak-info");
goto out;
}
if (_srt_file_test_in_sysroot (self->sysroot, self->sysroot_fd,
"/run/pressure-vessel", G_FILE_TEST_IS_DIR))
{
self->container.type = SRT_CONTAINER_TYPE_PRESSURE_VESSEL;
g_debug ("pressure-vessel based on /run/pressure-vessel");
goto out;
}
if (_srt_file_test_in_sysroot (self->sysroot, self->sysroot_fd,
"/.dockerenv", G_FILE_TEST_EXISTS))
{
self->container.type = SRT_CONTAINER_TYPE_DOCKER;
g_debug ("Docker based on /.dockerenv");
goto out;
}
if (_srt_file_test_in_sysroot (self->sysroot, self->sysroot_fd,
"/run/.containerenv", G_FILE_TEST_EXISTS))
{
self->container.type = SRT_CONTAINER_TYPE_PODMAN;
g_debug ("Podman based on /run/.containerenv");
goto out;
}
if (_srt_file_get_contents_in_sysroot (self->sysroot_fd,
"/proc/1/cgroup",
&contents, NULL, NULL))
{
if (strstr (contents, "/docker/") != NULL)
self->container.type = SRT_CONTAINER_TYPE_DOCKER;
if (self->container.type != SRT_CONTAINER_TYPE_UNKNOWN)
{
g_debug ("Type %d based on /proc/1/cgroup", self->container.type);
goto out;
}
g_clear_pointer (&contents, g_free);
}
g_return_if_fail (SRT_IS_SYSTEM_INFO (self));
if (run_host_fd >= 0)
{
g_debug ("Unknown container technology based on /run/host");
self->container.type = SRT_CONTAINER_TYPE_UNKNOWN;
goto out;
}
if (self->container_info == NULL && !self->immutable_values)
self->container_info = _srt_check_container (self->sysroot_fd, self->sysroot);
}
/* We haven't found any particular evidence of being in a container */
g_debug ("Probably not a container");
self->container.type = SRT_CONTAINER_TYPE_NONE;
/**
* srt_system_info_check_container:
* @self: The #SrtSystemInfo object
*
* Gather and return information about the container that is currently in use.
*
* Returns: (transfer full): An #SrtContainerInfo object.
* Free with g_object_unref().
*/
SrtContainerInfo *
srt_system_info_check_container (SrtSystemInfo *self)
{
g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
out:
self->container.have_data = TRUE;
ensure_container_info (self);
return g_object_ref (self->container_info);
}
/**
......@@ -4023,7 +3892,7 @@ srt_system_info_get_container_type (SrtSystemInfo *self)
g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), SRT_CONTAINER_TYPE_UNKNOWN);
ensure_container_info (self);
return self->container.type;
return srt_container_info_get_container_type (self->container_info);
}
/**
......@@ -4048,60 +3917,7 @@ srt_system_info_dup_container_host_directory (SrtSystemInfo *self)
g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
ensure_container_info (self);
return g_strdup (self->container.host_directory);
}
/**
* _srt_system_info_get_container_info_from_report:
* @json_obj: (not nullable): A JSON Object used to search for "container"
* property
* @host_path: (not nullable): Used to return the host path
*
* If the provided @json_obj doesn't have a "container" member,
* %SRT_CONTAINER_TYPE_UNKNOWN will be returned.
* If @json_obj has some elements that we can't parse, the returned
* #SrtContainerType will be set to %SRT_CONTAINER_TYPE_UNKNOWN.
*
* Returns: The found container type
*/
static SrtContainerType
_srt_system_info_get_container_info_from_report (JsonObject *json_obj,
gchar **host_path)
{
JsonObject *json_sub_obj;
JsonObject *json_host_obj = NULL;
const gchar *type_string = NULL;
SrtContainerType ret = SRT_CONTAINER_TYPE_UNKNOWN;
g_return_val_if_fail (host_path != NULL && *host_path == NULL, SRT_CONTAINER_TYPE_UNKNOWN);
if (json_object_has_member (json_obj, "container"))
{
json_sub_obj = json_object_get_object_member (json_obj, "container");
if (json_sub_obj == NULL)
goto out;
if (json_object_has_member (json_sub_obj, "type"))
{
type_string = json_object_get_string_member (json_sub_obj, "type");
if (!srt_enum_from_nick (SRT_TYPE_CONTAINER_TYPE, type_string, &ret, NULL))
{
g_debug ("The parsed container type '%s' is not a known element", type_string);
ret = SRT_CONTAINER_TYPE_UNKNOWN;
}
}
if (json_object_has_member (json_sub_obj, "host"))
{
json_host_obj = json_object_get_object_member (json_sub_obj, "host");
*host_path = g_strdup (json_object_get_string_member_with_default (json_host_obj, "path",
NULL));
}
}
out:
return ret;
return g_strdup (srt_container_info_get_container_host_directory (self->container_info));
}
static void
......@@ -4267,7 +4083,7 @@ ensure_xdg_portals_cached (SrtSystemInfo *self)
_srt_check_xdg_portals (self->env,
self->helpers_path,
self->test_flags,
self->container.type,
srt_container_info_get_container_type (self->container_info),
srt_system_info_get_primary_multiarch_tuple (self),
&self->xdg_portal_data);
}
......
......@@ -32,6 +32,7 @@
#include <glib.h>
#include <glib-object.h>
#include <steam-runtime-tools/container.h>
#include <steam-runtime-tools/cpu-feature.h>
#include <steam-runtime-tools/graphics.h>
#include <steam-runtime-tools/library.h>
......@@ -74,28 +75,6 @@ typedef enum
SRT_DRIVER_FLAGS_NONE = 0
} SrtDriverFlags;
/**
* SrtContainerType:
* @SRT_CONTAINER_TYPE_UNKNOWN: Unknown container type
* @SRT_CONTAINER_TYPE_NONE: No container detected
* @SRT_CONTAINER_TYPE_FLATPAK: Running in a Flatpak app
* @SRT_CONTAINER_TYPE_PRESSURE_VESSEL: Running in a Steam Runtime container
* using pressure-vessel
* @SRT_CONTAINER_TYPE_DOCKER: Running in a Docker container
* @SRT_CONTAINER_TYPE_PODMAN: Running in a Podman container
*
* A type of container.
*/
typedef enum
{
SRT_CONTAINER_TYPE_NONE = 0,
SRT_CONTAINER_TYPE_FLATPAK,
SRT_CONTAINER_TYPE_PRESSURE_VESSEL,
SRT_CONTAINER_TYPE_DOCKER,
SRT_CONTAINER_TYPE_PODMAN,
SRT_CONTAINER_TYPE_UNKNOWN = -1
} SrtContainerType;
typedef struct _SrtSystemInfo SrtSystemInfo;
typedef struct _SrtSystemInfoClass SrtSystemInfoClass;
......@@ -120,6 +99,8 @@ _SRT_PUBLIC
gboolean srt_system_info_can_run (SrtSystemInfo *self,
const char *multiarch_tuple);
_SRT_PUBLIC
SrtContainerInfo *srt_system_info_check_container (SrtSystemInfo *self);
_SRT_PUBLIC
SrtContainerType srt_system_info_get_container_type (SrtSystemInfo *self);
_SRT_PUBLIC
gchar *srt_system_info_dup_container_host_directory (SrtSystemInfo *self);
......
......@@ -27,6 +27,7 @@
#pragma once
#include "steam-runtime-tools/steam-runtime-tools.h"
#include "steam-runtime-tools/container-internal.h"
#include <json-glib/json-glib.h>
......
......@@ -25,6 +25,7 @@
#include "steam-runtime-tools/xdg-portal.h"
#include "steam-runtime-tools/container-internal.h"
#include "steam-runtime-tools/enums.h"
#include "steam-runtime-tools/glib-backports-internal.h"
#include "steam-runtime-tools/json-glib-backports-internal.h"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment