mirror of
https://github.com/flatpak/flatpak.git
synced 2026-03-17 22:49:36 -04:00
Merge pull request #2060 from matthiasclasen/instance-api
Add an instance api
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "flatpak-builtins.h"
|
||||
#include "flatpak-table-printer.h"
|
||||
#include "flatpak-run-private.h"
|
||||
#include "flatpak-instance-private.h"
|
||||
|
||||
static gboolean opt_show_cols;
|
||||
static const char **opt_cols;
|
||||
@@ -129,121 +129,16 @@ show_columns (void)
|
||||
g_print ("%s", col_help);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_instance_pid (const char *instance)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
char *pid;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
path = g_build_filename (g_get_user_runtime_dir (), ".flatpak", instance, "pid", NULL);
|
||||
|
||||
if (!g_file_get_contents (path, &pid, NULL, &error))
|
||||
{
|
||||
g_debug ("Failed to load pid file for instance '%s': %s", instance, error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static int
|
||||
get_child_pid (const char *instance)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
gsize length;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(JsonParser) parser = NULL;
|
||||
g_autoptr(JsonNode) node = NULL;
|
||||
g_autoptr(JsonObject) obj = NULL;
|
||||
|
||||
path = g_build_filename (g_get_user_runtime_dir (), ".flatpak", instance, "bwrapinfo.json", NULL);
|
||||
|
||||
if (!g_file_get_contents (path, &contents, &length, &error))
|
||||
{
|
||||
g_debug ("Failed to load bwrapinfo.json file for instance '%s': %s", instance, error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
parser = json_parser_new ();
|
||||
if (!json_parser_load_from_data (parser, contents, length, &error))
|
||||
{
|
||||
g_debug ("Failed to parse bwrapinfo.json file for instance '%s': %s", instance, error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = json_parser_get_root (parser);
|
||||
obj = json_node_get_object (node);
|
||||
|
||||
return json_object_get_int_member (obj, "child-pid");
|
||||
}
|
||||
|
||||
static GKeyFile *
|
||||
get_instance_info (const char *instance)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
GKeyFile *key_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
path = g_build_filename (g_get_user_runtime_dir (), ".flatpak", instance, "info", NULL);
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
|
||||
{
|
||||
g_debug ("Failed to load info file for instance '%s': %s", instance, error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_instance_column (GKeyFile *info,
|
||||
const char *name)
|
||||
{
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
if (strcmp (name, "application") == 0)
|
||||
return g_key_file_get_string (info, "Application", "name", NULL);
|
||||
if (strcmp (name, "arch") == 0)
|
||||
return g_key_file_get_string (info, "Instance", "arch", NULL);
|
||||
if (strcmp (name, "branch") == 0)
|
||||
return g_key_file_get_string (info, "Instance", "branch", NULL);
|
||||
else if (strcmp (name, "commit") == 0)
|
||||
return g_key_file_get_string (info, "Instance", "app-commit", NULL);
|
||||
else if (strcmp (name, "runtime") == 0)
|
||||
{
|
||||
g_autofree char *full_ref = g_key_file_get_string (info, "Application", "runtime", NULL);
|
||||
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
|
||||
return g_strdup (ref[1]);
|
||||
}
|
||||
else if (strcmp (name, "runtime-branch") == 0)
|
||||
{
|
||||
g_autofree char *full_ref = g_key_file_get_string (info, "Application", "runtime", NULL);
|
||||
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
|
||||
return g_strdup (ref[3]);
|
||||
}
|
||||
else if (strcmp (name, "runtime-commit") == 0)
|
||||
return g_key_file_get_string (info, "Instance", "runtime-commit", NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enumerate_instances (const char *columns,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *base_dir = NULL;
|
||||
g_autoptr(GFile) file = NULL;
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
GFileInfo *dir_info;
|
||||
g_autoptr(GPtrArray) instances = NULL;
|
||||
FlatpakTablePrinter *printer;
|
||||
g_auto(GStrv) cols = NULL;
|
||||
g_autofree int *col_idx = NULL;
|
||||
int n_cols;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
cols = g_strsplit (columns, ",", 0);
|
||||
n_cols = g_strv_length (cols);
|
||||
@@ -263,40 +158,58 @@ enumerate_instances (const char *columns,
|
||||
for (i = 0; i < n_cols; i++)
|
||||
flatpak_table_printer_set_column_title (printer, i + 1, all_columns[col_idx[i]].title);
|
||||
|
||||
base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL);
|
||||
file = g_file_new_for_path (base_dir);
|
||||
enumerator = g_file_enumerate_children (file, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, error);
|
||||
if (enumerator == NULL)
|
||||
instances = flatpak_instance_get_all ();
|
||||
if (instances->len == 0)
|
||||
{
|
||||
if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
/* nothing to show */
|
||||
g_clear_error (error);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
/* nothing to show */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while ((dir_info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL)
|
||||
for (j = 0; j < instances->len; j++)
|
||||
{
|
||||
g_autofree char *instance = g_file_info_get_attribute_as_string (dir_info, "standard::name");
|
||||
g_autoptr(GKeyFile) info = get_instance_info (instance);
|
||||
FlatpakInstance *instance = (FlatpakInstance *)g_ptr_array_index (instances, j);
|
||||
|
||||
flatpak_table_printer_add_column (printer, instance);
|
||||
flatpak_table_printer_add_column (printer, flatpak_instance_get_id (instance));
|
||||
|
||||
for (i = 0; i < n_cols; i++)
|
||||
{
|
||||
g_autofree char *col = NULL;
|
||||
g_autofree char *freeme = NULL;
|
||||
const char *col = NULL;
|
||||
int idx = col_idx[i];
|
||||
int len;
|
||||
|
||||
if (strcmp (all_columns[col_idx[i]].name, "pid") == 0)
|
||||
col = get_instance_pid (instance);
|
||||
else if (strcmp (all_columns[col_idx[i]].name, "child-pid") == 0)
|
||||
col = g_strdup_printf ("%d", get_child_pid (instance));
|
||||
else
|
||||
col = get_instance_column (info, all_columns[col_idx[i]].name);
|
||||
if (strcmp (all_columns[idx].name, "pid") == 0)
|
||||
col = freeme = g_strdup_printf ("%d", flatpak_instance_get_pid (instance));
|
||||
else if (strcmp (all_columns[idx].name, "child-pid") == 0)
|
||||
col = freeme = g_strdup_printf ("%d", flatpak_instance_get_child_pid (instance));
|
||||
else if (strcmp (all_columns[idx].name, "application") == 0)
|
||||
col = flatpak_instance_get_app (instance);
|
||||
else if (strcmp (all_columns[idx].name, "arch") == 0)
|
||||
col = flatpak_instance_get_arch (instance);
|
||||
else if (strcmp (all_columns[idx].name, "commit") == 0)
|
||||
col = flatpak_instance_get_commit (instance);
|
||||
else if (strcmp (all_columns[idx].name, "runtime") == 0)
|
||||
{
|
||||
const char *full_ref = flatpak_instance_get_runtime (instance);
|
||||
if (full_ref != NULL)
|
||||
{
|
||||
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
|
||||
col = freeme = g_strdup (ref[1]);
|
||||
}
|
||||
}
|
||||
else if (strcmp (all_columns[idx].name, "runtime-branch") == 0)
|
||||
{
|
||||
const char *full_ref = flatpak_instance_get_runtime (instance);
|
||||
if (full_ref != NULL)
|
||||
{
|
||||
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
|
||||
col = freeme = g_strdup (ref[3]);
|
||||
}
|
||||
}
|
||||
else if (strcmp (all_columns[idx].name, "runtime-commit") == 0)
|
||||
col = flatpak_instance_get_runtime_commit (instance);
|
||||
|
||||
len = all_columns[col_idx[i]].len;
|
||||
len = all_columns[idx].len;
|
||||
if (len == 0)
|
||||
flatpak_table_printer_add_column (printer, col);
|
||||
else
|
||||
@@ -304,24 +217,35 @@ enumerate_instances (const char *columns,
|
||||
}
|
||||
|
||||
flatpak_table_printer_finish_row (printer);
|
||||
|
||||
g_object_unref (dir_info);
|
||||
}
|
||||
|
||||
flatpak_table_printer_print (printer);
|
||||
flatpak_table_printer_free (printer);
|
||||
|
||||
if (*error)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
list_has (const char *list,
|
||||
const char *term)
|
||||
{
|
||||
const char *p;
|
||||
int len;
|
||||
|
||||
p = strstr (list, term);
|
||||
len = strlen (term);
|
||||
if (p &&
|
||||
(p == list || p[-1] == ',') &&
|
||||
(p[len] == '\0' || p[len] == ','))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_builtin_ps (int argc,
|
||||
char **argv,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
flatpak_builtin_ps (int argc,
|
||||
char **argv,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autofree char *col_help = NULL;
|
||||
@@ -341,8 +265,6 @@ flatpak_builtin_ps (int argc,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flatpak_run_gc_ids ();
|
||||
|
||||
if (opt_show_cols)
|
||||
{
|
||||
show_columns ();
|
||||
@@ -351,38 +273,24 @@ flatpak_builtin_ps (int argc,
|
||||
|
||||
if (opt_cols)
|
||||
{
|
||||
gboolean show_help = FALSE;
|
||||
gboolean show_all = FALSE;
|
||||
int i;
|
||||
|
||||
for (i = 0; opt_cols[i]; i++)
|
||||
{
|
||||
const char *p;
|
||||
p = strstr (opt_cols[i], "help");
|
||||
if (p &&
|
||||
(p == opt_cols[i] || p[-1] == ',') &&
|
||||
(p[strlen("help")] == '\0' || p[strlen("help")] == ','))
|
||||
if (list_has (opt_cols[i], "help"))
|
||||
{
|
||||
show_help = TRUE;
|
||||
break;
|
||||
show_columns ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
p = strstr (opt_cols[i], "all");
|
||||
if (p &&
|
||||
(p == opt_cols[i] || p[-1] == ',') &&
|
||||
(p[strlen("all")] == '\0' || p[strlen("all")] == ','))
|
||||
if (list_has (opt_cols[i], "all"))
|
||||
{
|
||||
show_all = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (show_help)
|
||||
{
|
||||
show_columns ();
|
||||
return TRUE;
|
||||
}
|
||||
else if (show_all)
|
||||
if (show_all)
|
||||
{
|
||||
cols = g_strdup (ALL_COLUMNS);
|
||||
}
|
||||
|
||||
@@ -120,6 +120,8 @@ libflatpak_common_la_SOURCES = \
|
||||
common/flatpak-error.c \
|
||||
common/flatpak-installation-private.h \
|
||||
common/flatpak-installation.c \
|
||||
common/flatpak-instance-private.h \
|
||||
common/flatpak-instance.c \
|
||||
common/valgrind-private.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
68
common/flatpak-instance-private.h
Normal file
68
common/flatpak-instance-private.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright © 2018 Red Hat, Inc
|
||||
*
|
||||
* This program 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION)
|
||||
#error "Only <flatpak.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __FLATPAK_INSTANCE_H__
|
||||
#define __FLATPAK_INSTANCE_H__
|
||||
|
||||
typedef struct _FlatpakInstance FlatpakInstance;
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define FLATPAK_TYPE_INSTANCE flatpak_instance_get_type ()
|
||||
#define FLATPAK_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_INSTANCE, FlatpakInstance))
|
||||
#define FLATPAK_IS_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_INSTANCE))
|
||||
|
||||
FLATPAK_EXTERN GType flatpak_instance_get_type (void);
|
||||
|
||||
struct _FlatpakInstance
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
} FlatpakInstanceClass;
|
||||
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakInstance, g_object_unref)
|
||||
#endif
|
||||
|
||||
FLATPAK_EXTERN GPtrArray * flatpak_instance_get_all (void);
|
||||
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_id (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_app (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_arch (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_branch (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_commit (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_runtime (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN const char * flatpak_instance_get_runtime_commit (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN int flatpak_instance_get_pid (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN int flatpak_instance_get_child_pid (FlatpakInstance *self);
|
||||
FLATPAK_EXTERN GKeyFile * flatpak_instance_get_info (FlatpakInstance *self);
|
||||
|
||||
FLATPAK_EXTERN gboolean flatpak_instance_is_running (FlatpakInstance *self);
|
||||
|
||||
#endif /* __FLATPAK_INSTANCE_H__ */
|
||||
353
common/flatpak-instance.c
Normal file
353
common/flatpak-instance.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright © 2018 Red Hat, Inc
|
||||
*
|
||||
* This program 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-run-private.h"
|
||||
#include "flatpak-instance-private.h"
|
||||
#include "flatpak-enum-types.h"
|
||||
|
||||
|
||||
typedef struct _FlatpakInstancePrivate FlatpakInstancePrivate;
|
||||
|
||||
struct _FlatpakInstancePrivate
|
||||
{
|
||||
char *id;
|
||||
char *dir;
|
||||
|
||||
GKeyFile *info;
|
||||
char *app;
|
||||
char *arch;
|
||||
char *branch;
|
||||
char *commit;
|
||||
char *runtime;
|
||||
char *runtime_commit;
|
||||
|
||||
int pid;
|
||||
int child_pid;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (FlatpakInstance, flatpak_instance, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
flatpak_instance_finalize (GObject *object)
|
||||
{
|
||||
FlatpakInstance *self = FLATPAK_INSTANCE (object);
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
g_free (priv->id);
|
||||
g_free (priv->dir);
|
||||
g_free (priv->app);
|
||||
g_free (priv->arch);
|
||||
g_free (priv->branch);
|
||||
g_free (priv->commit);
|
||||
g_free (priv->runtime);
|
||||
g_free (priv->runtime_commit);
|
||||
|
||||
if (priv->info)
|
||||
g_key_file_unref (priv->info);
|
||||
|
||||
G_OBJECT_CLASS (flatpak_instance_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_instance_class_init (FlatpakInstanceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = flatpak_instance_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_instance_init (FlatpakInstance *self)
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_id (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->id;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_app (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->app;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_arch (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->arch;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_branch (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->branch;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_commit (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->commit;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_runtime (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->runtime;
|
||||
}
|
||||
|
||||
const char *
|
||||
flatpak_instance_get_runtime_commit (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->runtime_commit;
|
||||
}
|
||||
|
||||
int
|
||||
flatpak_instance_get_pid (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->pid;
|
||||
}
|
||||
|
||||
int
|
||||
flatpak_instance_get_child_pid (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->child_pid;
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
flatpak_instance_get_info (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
return priv->info;
|
||||
}
|
||||
|
||||
static GKeyFile *
|
||||
get_instance_info (const char *dir)
|
||||
{
|
||||
g_autofree char *file = NULL;
|
||||
g_autoptr(GKeyFile) key_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
file = g_build_filename (dir, "info", NULL);
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (key_file, file, G_KEY_FILE_NONE, &error))
|
||||
{
|
||||
g_debug ("Failed to load instance info file '%s': %s", file, error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_steal_pointer (&key_file);
|
||||
}
|
||||
|
||||
static int
|
||||
get_child_pid (const char *dir)
|
||||
{
|
||||
g_autofree char *file = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
gsize length;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(JsonParser) parser = NULL;
|
||||
JsonNode *node;
|
||||
JsonObject *obj;
|
||||
|
||||
file = g_build_filename (dir, "bwrapinfo.json", NULL);
|
||||
|
||||
if (!g_file_get_contents (file, &contents, &length, &error))
|
||||
{
|
||||
g_debug ("Failed to load bwrapinfo.json file '%s': %s", file, error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
parser = json_parser_new ();
|
||||
if (!json_parser_load_from_data (parser, contents, length, &error))
|
||||
{
|
||||
g_debug ("Failed to parse bwrapinfo.json file '%s': %s", file, error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = json_parser_get_root (parser);
|
||||
obj = json_node_get_object (node);
|
||||
|
||||
return json_object_get_int_member (obj, "child-pid");
|
||||
}
|
||||
|
||||
static int
|
||||
get_pid (const char *dir)
|
||||
{
|
||||
g_autofree char *file = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
file = g_build_filename (dir, "pid", NULL);
|
||||
|
||||
if (!g_file_get_contents (file, &contents, NULL, &error))
|
||||
{
|
||||
g_debug ("Failed to load pid file '%s': %s", file, error->message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) g_ascii_strtoll (contents, NULL, 10);
|
||||
}
|
||||
|
||||
static FlatpakInstance *
|
||||
flatpak_instance_new (const char *id)
|
||||
{
|
||||
FlatpakInstance *self = g_object_new (flatpak_instance_get_type (), NULL);
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
priv->id = g_strdup (id);
|
||||
|
||||
priv->dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", id, NULL);
|
||||
|
||||
priv->pid = get_pid (priv->dir);
|
||||
priv->child_pid = get_child_pid (priv->dir);
|
||||
priv->info = get_instance_info (priv->dir);
|
||||
|
||||
if (priv->info)
|
||||
{
|
||||
priv->app = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_APPLICATION, FLATPAK_METADATA_KEY_NAME, NULL);
|
||||
priv->runtime = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_APPLICATION, FLATPAK_METADATA_KEY_RUNTIME, NULL);
|
||||
|
||||
priv->arch = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_INSTANCE, FLATPAK_METADATA_KEY_ARCH, NULL);
|
||||
priv->branch = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_INSTANCE, FLATPAK_METADATA_KEY_BRANCH, NULL);
|
||||
priv->commit = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_INSTANCE, FLATPAK_METADATA_KEY_APP_COMMIT, NULL);
|
||||
priv->runtime_commit = g_key_file_get_string (priv->info,
|
||||
FLATPAK_METADATA_GROUP_INSTANCE, FLATPAK_METADATA_KEY_RUNTIME_COMMIT, NULL);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
flatpak_instance_get_all (void)
|
||||
{
|
||||
g_autoptr(GPtrArray) instances = NULL;
|
||||
g_autofree char *base_dir = NULL;
|
||||
g_auto(GLnxDirFdIterator) iter = { 0 };
|
||||
struct dirent *dent;
|
||||
|
||||
instances = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL);
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (AT_FDCWD, base_dir, FALSE, &iter, NULL))
|
||||
return g_steal_pointer (&instances);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&iter, &dent, NULL, NULL))
|
||||
break;
|
||||
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
if (dent->d_type == DT_DIR)
|
||||
{
|
||||
g_autofree char *ref_file = g_strconcat (dent->d_name, "/.ref", NULL);
|
||||
struct stat statbuf;
|
||||
struct flock l = {
|
||||
.l_type = F_WRLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
glnx_autofd int lock_fd = openat (iter.fd, ref_file, O_RDWR | O_CLOEXEC);
|
||||
if (lock_fd != -1 &&
|
||||
fstat (lock_fd, &statbuf) == 0 &&
|
||||
/* Only gc if created at least 3 secs ago, to work around race mentioned in flatpak_run_allocate_id() */
|
||||
statbuf.st_mtime + 3 < time (NULL) &&
|
||||
fcntl (lock_fd, F_GETLK, &l) == 0 &&
|
||||
l.l_type == F_UNLCK)
|
||||
{
|
||||
/* The instance is not used, remove it */
|
||||
g_debug ("Cleaning up unused container id %s", dent->d_name);
|
||||
glnx_shutil_rm_rf_at (iter.fd, dent->d_name, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_ptr_array_add (instances, flatpak_instance_new (dent->d_name));
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&instances);
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_instance_is_running (FlatpakInstance *self)
|
||||
{
|
||||
FlatpakInstancePrivate *priv = flatpak_instance_get_instance_private (self);
|
||||
|
||||
if (priv->dir)
|
||||
{
|
||||
g_autofree char *ref_file = g_strconcat (priv->dir, "/.ref", NULL);
|
||||
struct stat statbuf;
|
||||
struct flock l = {
|
||||
.l_type = F_WRLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
glnx_autofd int lock_fd = open (ref_file, O_RDWR | O_CLOEXEC);
|
||||
if (lock_fd != -1 &&
|
||||
fstat (lock_fd, &statbuf) == 0 &&
|
||||
/* Only gc if created at least 3 secs ago, to work around race mentioned in flatpak_run_allocate_id() */
|
||||
statbuf.st_mtime + 3 < time (NULL) &&
|
||||
fcntl (lock_fd, F_GETLK, &l) == 0 &&
|
||||
l.l_type == F_UNLCK)
|
||||
{
|
||||
/* The instance is not used, remove it */
|
||||
g_debug ("Cleaning up unused container id %s", priv->id);
|
||||
glnx_shutil_rm_rf_at (-1, priv->dir, NULL, NULL);
|
||||
|
||||
g_clear_pointer (&priv->dir, g_free);
|
||||
}
|
||||
}
|
||||
|
||||
return priv->dir != NULL;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,4 @@ gboolean flatpak_run_app (const char *app_ref,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void flatpak_run_gc_ids (void);
|
||||
|
||||
#endif /* __FLATPAK_RUN_H__ */
|
||||
|
||||
@@ -1571,7 +1571,7 @@ flatpak_app_compute_permissions (GKeyFile *app_metadata,
|
||||
return g_steal_pointer (&app_context);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
flatpak_run_gc_ids (void)
|
||||
{
|
||||
g_autofree char *base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL);
|
||||
|
||||
Reference in New Issue
Block a user