[sysprof/wip/chergert/path-resolver] podman: include image layers in overlay
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof/wip/chergert/path-resolver] podman: include image layers in overlay
- Date: Tue, 21 Sep 2021 22:36:27 +0000 (UTC)
commit e62d6a07a2fcdf194400e171b64a1f86239a07f6
Author: Christian Hergert <chergert redhat com>
Date: Tue Sep 21 15:36:18 2021 -0700
podman: include image layers in overlay
We want the image layers so we can find the files in the base image
correctly.
src/libsysprof/sysprof-podman.c | 123 ++++++++++++++++++++++++++++++++++------
1 file changed, 105 insertions(+), 18 deletions(-)
---
diff --git a/src/libsysprof/sysprof-podman.c b/src/libsysprof/sysprof-podman.c
index 2832f79..880bc6c 100644
--- a/src/libsysprof/sysprof-podman.c
+++ b/src/libsysprof/sysprof-podman.c
@@ -74,6 +74,7 @@ struct _SysprofPodman
{
JsonParser *containers_parser;
JsonParser *layers_parser;
+ JsonParser *images_parser;
};
void
@@ -81,6 +82,7 @@ sysprof_podman_free (SysprofPodman *self)
{
g_clear_object (&self->containers_parser);
g_clear_object (&self->layers_parser);
+ g_clear_object (&self->images_parser);
g_slice_free (SysprofPodman, self);
}
@@ -116,6 +118,22 @@ load_layers (SysprofPodman *self)
json_parser_load_from_file (self->layers_parser, path, NULL);
}
+static void
+load_images (SysprofPodman *self)
+{
+ g_autofree char *path = NULL;
+
+ g_assert (self != NULL);
+
+ path = g_build_filename (g_get_user_data_dir (),
+ "containers",
+ "storage",
+ "overlay-images",
+ "images.json",
+ NULL);
+ json_parser_load_from_file (self->images_parser, path, NULL);
+}
+
SysprofPodman *
sysprof_podman_snapshot_current_user (void)
{
@@ -124,17 +142,57 @@ sysprof_podman_snapshot_current_user (void)
self = g_slice_new0 (SysprofPodman);
self->containers_parser = json_parser_new ();
self->layers_parser = json_parser_new ();
+ self->images_parser = json_parser_new ();
load_containers (self);
load_layers (self);
+ load_images (self);
return self;
}
+static const char *
+find_image_layer (JsonParser *parser,
+ const char *image)
+{
+ JsonNode *root;
+ JsonArray *ar;
+ guint n_items;
+
+ g_assert (JSON_IS_PARSER (parser));
+ g_assert (image != NULL);
+
+ if (!(root = json_parser_get_root (parser)) ||
+ !JSON_NODE_HOLDS_ARRAY (root) ||
+ !(ar = json_node_get_array (root)))
+ return NULL;
+
+ n_items = json_array_get_length (ar);
+
+ for (guint i = 0; i < n_items; i++)
+ {
+ JsonObject *item = json_array_get_object_element (ar, i);
+ const char *id;
+ const char *layer;
+
+ if (item == NULL ||
+ !json_object_has_member (item, "id") ||
+ !json_object_has_member (item, "layer") ||
+ !(id = json_object_get_string_member (item, "id")) ||
+ strcmp (id, image) != 0 ||
+ !(layer = json_object_get_string_member (item, "layer")))
+ continue;
+
+ return layer;
+ }
+
+ return NULL;
+}
+
static const char *
find_parent_layer (JsonParser *parser,
const char *layer,
- GPtrArray *seen)
+ GHashTable *seen)
{
JsonNode *root;
JsonArray *ar;
@@ -165,12 +223,8 @@ find_parent_layer (JsonParser *parser,
!(parent = json_object_get_string_member (item, "parent")))
continue;
- /* Avoid cycles by checking if we've seen this parent */
- for (guint j = 0; j < seen->len; j++)
- {
- if (strcmp (parent, g_ptr_array_index (seen, j)) == 0)
- return NULL;
- }
+ if (g_hash_table_contains (seen, parent))
+ return NULL;
return parent;
}
@@ -178,14 +232,35 @@ find_parent_layer (JsonParser *parser,
return NULL;
}
+static char *
+get_layer_dir (const char *layer)
+{
+ /* We don't use XDG data dir because this might be in a container
+ * or flatpak environment that doesn't match. And generally, it's
+ * always .local.
+ */
+ return g_build_filename (g_get_home_dir (),
+ ".local",
+ "share",
+ "containers",
+ "storage",
+ "overlay",
+ layer,
+ "diff",
+ NULL);
+}
+
gchar **
sysprof_podman_get_layers (SysprofPodman *self,
const char *container)
{
const char *layer = NULL;
- GPtrArray *layers;
+ const char *image = NULL;
+ GHashTable *layers;
JsonNode *root;
JsonArray *ar;
+ const char **keys;
+ char **ret;
guint n_items;
g_return_val_if_fail (self != NULL, NULL);
@@ -214,18 +289,30 @@ sysprof_podman_get_layers (SysprofPodman *self,
continue;
layer = item_layer;
+ image = json_object_get_string_member (item, "image");
break;
}
- /* Now we need to try to locate the layer and all of the parents
- * within the layers.json so that we populate from the most recent
- * layer to those beneath it.
- */
- layers = g_ptr_array_new ();
- g_ptr_array_add (layers, g_strdup (layer));
- while ((layer = find_parent_layer (self->layers_parser, layer, layers)))
- g_ptr_array_add (layers, g_strdup (layer));
- g_ptr_array_add (layers, NULL);
+ layers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ /* Add all our known layers starting from current layer */
+ do
+ g_hash_table_add (layers, get_layer_dir (layer));
+ while ((layer = find_parent_layer (self->layers_parser, layer, layers)));
+
+ /* If an image was specified, add its layer */
+ if ((layer = find_image_layer (self->images_parser, image)))
+ {
+ do
+ g_hash_table_add (layers, get_layer_dir (layer));
+ while ((layer = find_parent_layer (self->layers_parser, layer, layers)));
+ }
+
+ keys = (const char **)g_hash_table_get_keys_as_array (layers, NULL);
+ ret = g_strdupv ((char **)keys);
+
+ g_hash_table_unref (layers);
+ g_free (keys);
- return (char **)g_ptr_array_free (layers, FALSE);
+ return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]