Convert all builtins to the new metadata/arg formats using XdgAppContext

This commit is contained in:
Alexander Larsson
2015-05-22 16:55:45 +02:00
parent 7ba3d09e29
commit 942e4bcdb6
5 changed files with 102 additions and 214 deletions

View File

@@ -31,15 +31,12 @@
#include "xdg-app-builtins.h"
#include "xdg-app-utils.h"
#include "xdg-app-run.h"
static char *opt_command;
static char **opt_allow;
static char **opt_env_override;
static GOptionEntry options[] = {
{ "command", 0, 0, G_OPTION_ARG_STRING, &opt_command, "Command to set", "COMMAND" },
{ "allow", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_allow, "Environment options to set to true", "KEY" },
{ "env", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_env_override, "Override an environment variable", "VARIABLE=[VALUE]" },
{ NULL }
};
@@ -216,19 +213,14 @@ out:
}
static gboolean
update_metadata (GFile *base, GCancellable *cancellable, GError **error)
update_metadata (GFile *base, XdgAppContext *arg_context, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) metadata = NULL;
g_autofree char *path = NULL;
g_autoptr(GKeyFile) keyfile = NULL;
g_autoptr(XdgAppContext) app_context = NULL;
GError *temp_error = NULL;
const char *environment_keys[] = {
"x11", "wayland", "ipc", "pulseaudio", "system-dbus", "session-dbus",
"network", "host-fs", "homedir", "dri", NULL
};
const char *key;
int i;
metadata = g_file_get_child (base, "metadata");
if (!g_file_query_exists (metadata, cancellable))
@@ -294,46 +286,11 @@ update_metadata (GFile *base, GCancellable *cancellable, GError **error)
}
}
g_debug ("Setting environment");
for (i = 0; environment_keys[i]; i++)
{
key = environment_keys[i];
g_key_file_set_boolean (keyfile, "Environment", key, FALSE);
}
if (opt_allow)
{
for (i = 0; opt_allow[i]; i++)
{
key = opt_allow[i];
if (!g_strv_contains (environment_keys, key))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown Environment key %s", key);
goto out;
}
g_key_file_set_boolean (keyfile, "Environment", key, TRUE);
}
}
if (opt_env_override)
{
for (i = 0; opt_env_override[i]; i++)
{
glnx_strfreev char **split = g_strsplit (opt_env_override[i], "=", 2);
if (split && split[0] && split[1])
{
g_key_file_set_string (keyfile, "Environment Vars", split[0], split[1]);
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cannot parse variable %s", opt_env_override[i]);
goto out;
}
}
}
app_context = xdg_app_context_new ();
if (!xdg_app_context_load_metadata (app_context, keyfile, error))
goto out;
xdg_app_context_merge (app_context, arg_context);
xdg_app_context_save_metadata (app_context, keyfile);
if (!g_key_file_save_to_file (keyfile, path, error))
goto out;
@@ -363,9 +320,13 @@ xdg_app_builtin_build_finish (int argc, char **argv, GCancellable *cancellable,
gsize metadata_size;
const char *directory;
g_autoptr(GKeyFile) metakey = NULL;
g_autoptr(XdgAppContext) arg_context = NULL;
context = g_option_context_new ("DIRECTORY - Convert a directory to a bundle");
arg_context = xdg_app_context_new ();
g_option_context_add_group (context, xdg_app_context_get_options (arg_context));
if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
goto out;
@@ -412,7 +373,7 @@ xdg_app_builtin_build_finish (int argc, char **argv, GCancellable *cancellable,
goto out;
g_debug ("Updating metadata");
if (!update_metadata (base, cancellable, error))
if (!update_metadata (base, arg_context, cancellable, error))
goto out;
g_print ("Please review the exported files and the metadata\n");

View File

@@ -34,13 +34,9 @@
#include "xdg-app-run.h"
static gboolean opt_runtime;
static char **opt_allow;
static char **opt_forbid;
static GOptionEntry options[] = {
{ "runtime", 'r', 0, G_OPTION_ARG_NONE, &opt_runtime, "Use non-devel runtime", NULL },
{ "allow", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_allow, "Environment options to set to true", "KEY" },
{ "forbid", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_forbid, "Environment options to set to false", "KEY" },
{ NULL }
};
@@ -77,6 +73,8 @@ xdg_app_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
g_autofree char *app_id = NULL;
int i;
int rest_argv_start, rest_argc;
g_autoptr(XdgAppContext) arg_context = NULL;
g_autoptr(XdgAppContext) app_context = NULL;
context = g_option_context_new ("DIRECTORY [COMMAND [args...]] - Build in directory");
@@ -93,6 +91,9 @@ xdg_app_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
}
}
arg_context = xdg_app_context_new ();
g_option_context_add_group (context, xdg_app_context_get_options (arg_context));
if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
goto out;
@@ -147,16 +148,15 @@ xdg_app_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
g_ptr_array_add (argv_array, g_strdup ("-H"));
g_ptr_array_add (argv_array, g_strdup ("-r"));
if (!xdg_app_run_verify_environment_keys ((const char **)opt_forbid, error))
app_context = xdg_app_context_new ();
if (!xdg_app_context_load_metadata (app_context, runtime_metakey, error))
goto out;
if (!xdg_app_run_verify_environment_keys ((const char **)opt_allow, error))
if (!xdg_app_context_load_metadata (app_context, metakey, error))
goto out;
xdg_app_context_merge (app_context, arg_context);
xdg_app_run_add_environment_args (argv_array, NULL, app_id,
runtime_metakey, metakey,
(const char **)opt_allow,
(const char **)opt_forbid);
app_context);
g_ptr_array_add (argv_array, g_strdup ("-w"));
g_ptr_array_add (argv_array, g_strdup ("-a"));
@@ -172,7 +172,7 @@ xdg_app_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
g_ptr_array_add (argv_array, NULL);
envp = xdg_app_run_get_minimal_env (TRUE);
envp = xdg_app_run_apply_env_vars (envp, runtime_metakey);
envp = xdg_app_run_apply_env_vars (envp, app_context);
if (!execve (HELPER, (char **)argv_array->pdata, envp))
{

View File

@@ -40,8 +40,6 @@ static char *opt_branch;
static char *opt_command;
static gboolean opt_devel;
static char *opt_runtime;
static char **opt_allow;
static char **opt_forbid;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Arch to use", "ARCH" },
@@ -49,8 +47,6 @@ static GOptionEntry options[] = {
{ "branch", 0, 0, G_OPTION_ARG_STRING, &opt_branch, "Branch to use", "BRANCH" },
{ "devel", 'd', 0, G_OPTION_ARG_NONE, &opt_devel, "Use development runtime", NULL },
{ "runtime", 0, 0, G_OPTION_ARG_STRING, &opt_runtime, "Runtime to use", "RUNTIME" },
{ "allow", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_allow, "Environment options to set to true", "KEY" },
{ "forbid", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_forbid, "Environment options to set to false", "KEY" },
{ NULL }
};
@@ -176,6 +172,8 @@ xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
int i;
int rest_argv_start, rest_argc;
int sync_proxy_pipes[2];
g_autoptr(XdgAppContext) arg_context = NULL;
g_autoptr(XdgAppContext) app_context = NULL;
context = g_option_context_new ("APP [args...] - Run an app");
@@ -192,6 +190,9 @@ xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
}
}
arg_context = xdg_app_context_new ();
g_option_context_add_group (context, xdg_app_context_get_options (arg_context));
if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
goto out;
@@ -251,6 +252,13 @@ xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
runtime_metakey = xdg_app_deploy_get_metadata (runtime_deploy);
app_context = xdg_app_context_new ();
if (!xdg_app_context_load_metadata (app_context, runtime_metakey, error))
goto out;
if (!xdg_app_context_load_metadata (app_context, metakey, error))
goto out;
xdg_app_context_merge (app_context, arg_context);
if (!add_extension_args (runtime_metakey, runtime_ref, argv_array, cancellable, error))
goto out;
@@ -284,16 +292,8 @@ xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
}
}
if (!xdg_app_run_verify_environment_keys ((const char **)opt_forbid, error))
goto out;
if (!xdg_app_run_verify_environment_keys ((const char **)opt_allow, error))
goto out;
xdg_app_run_add_environment_args (argv_array, dbus_proxy_argv,
app, runtime_metakey, metakey,
(const char **)opt_allow,
(const char **)opt_forbid);
app, app_context);
g_ptr_array_add (argv_array, g_strdup ("-b"));
g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/fonts=%s", SYSTEM_FONTS_DIR));
@@ -354,9 +354,7 @@ xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
envp = g_get_environ ();
envp = xdg_app_run_apply_env_default (envp);
envp = xdg_app_run_apply_env_vars (envp, runtime_metakey);
/* Load application environment overrides *after* runtime */
envp = xdg_app_run_apply_env_vars (envp, metakey);
envp = xdg_app_run_apply_env_vars (envp, app_context);
envp = xdg_app_run_apply_env_appid (envp, app_id_dir);

View File

@@ -985,80 +985,34 @@ xdg_app_run_add_session_dbus_args (GPtrArray *argv_array,
return FALSE;
}
static void
xdg_app_add_bus_filters_for_meta (GPtrArray *dbus_proxy_argv,
const char *header,
GKeyFile *metakey)
{
glnx_strfreev char **keys = NULL;
gsize i, keys_count;
keys = g_key_file_get_keys (metakey, header, &keys_count, NULL);
if (keys)
{
for (i = 0; i < keys_count; i++)
{
const char *key = keys[i];
const char *key_part;
g_autofree char *tmp = NULL;
g_autofree char *value = g_key_file_get_string (metakey, header, key, NULL);
if (g_str_has_suffix (key, ".*"))
{
tmp = g_strndup (key, strlen (key) - 2);
key_part = tmp;
}
else
key_part = key;
if (!(g_dbus_is_name (key_part) && !g_dbus_is_unique_name (key_part)))
{
g_warning ("Invalid dbus name %s\n", key);
continue;
}
if (strcmp (value, "see") != 0 &&
strcmp (value, "talk") != 0 &&
strcmp (value, "own") != 0)
{
g_warning ("Invalid dbus policy: %s\n", value);
continue;
}
g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--%s=%s", value, key));
}
}
}
static void
xdg_app_add_bus_filters (GPtrArray *dbus_proxy_argv,
const char *app_id,
GKeyFile *runtime_metakey,
GKeyFile *metakey)
XdgAppContext *context)
{
GHashTableIter iter;
gpointer key, value;
g_ptr_array_add (dbus_proxy_argv, g_strdup ("--filter"));
g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--own=%s", app_id));
g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--own=%s.*", app_id));
xdg_app_add_bus_filters_for_meta (dbus_proxy_argv,
XDG_APP_METADATA_GROUP_SESSION_BUS_POLICY,
runtime_metakey);
if (metakey)
xdg_app_add_bus_filters_for_meta (dbus_proxy_argv,
XDG_APP_METADATA_GROUP_SESSION_BUS_POLICY,
metakey);
g_hash_table_iter_init (&iter, context->bus_policy);
while (g_hash_table_iter_next (&iter, &key, &value))
{
XdgAppPolicy policy = GPOINTER_TO_INT (value);
if (policy > 0)
g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--%s=%s", xdg_app_policy_to_string (policy), (char *)key));
}
}
void
xdg_app_run_add_environment_args (GPtrArray *argv_array,
GPtrArray *dbus_proxy_argv,
const char *app_id,
GKeyFile *runtime_metakey,
GKeyFile *metakey,
const char **allow,
const char **forbid)
XdgAppContext *context)
{
const char *no_opts[1] = { NULL };
gboolean unrestricted_session_bus;
char opts[16];
int i;
@@ -1066,89 +1020,67 @@ xdg_app_run_add_environment_args (GPtrArray *argv_array,
i = 0;
opts[i++] = '-';
if (allow == NULL)
allow = no_opts;
if (forbid == NULL)
forbid = no_opts;
if ((g_key_file_get_boolean (metakey, "Environment", "ipc", NULL) || g_strv_contains (allow, "ipc")) &&
!g_strv_contains (forbid, "ipc"))
if (context->shares & XDG_APP_CONTEXT_SHARED_IPC)
{
g_debug ("Allowing ipc access");
opts[i++] = 'i';
}
if ((g_key_file_get_boolean (metakey, "Environment", "dri", NULL) || g_strv_contains (allow, "dri")) &&
!g_strv_contains (forbid, "dri"))
{
g_debug ("Allowing dri access");
opts[i++] = 'g';
}
if ((g_key_file_get_boolean (metakey, "Environment", "host-fs", NULL) || g_strv_contains (allow, "nost-fs")) &&
!g_strv_contains (forbid, "host-fs"))
{
g_debug ("Allowing host-fs access");
opts[i++] = 'f';
}
if ((g_key_file_get_boolean (metakey, "Environment", "homedir", NULL) || g_strv_contains (allow, "homedir")) &&
!g_strv_contains (forbid, "homedir"))
{
g_debug ("Allowing homedir access");
opts[i++] = 'H';
}
if ((g_key_file_get_boolean (metakey, "Environment", "network", NULL) || g_strv_contains (allow, "network")) &&
!g_strv_contains (forbid, "network"))
if (context->shares & XDG_APP_CONTEXT_SHARED_NETWORK)
{
g_debug ("Allowing network access");
opts[i++] = 'n';
}
if ((g_key_file_get_boolean (metakey, "Environment", "x11", NULL) || g_strv_contains (allow, "x11")) &&
!g_strv_contains (forbid, "x11"))
if (context->devices & XDG_APP_CONTEXT_DEVICE_DRI)
{
g_debug ("Allowing dri access");
opts[i++] = 'g';
}
if (g_hash_table_lookup (context->filesystems, "host"))
{
g_debug ("Allowing host-fs access");
opts[i++] = 'f';
}
else if (g_hash_table_lookup (context->filesystems, "home"))
{
g_debug ("Allowing homedir access");
opts[i++] = 'H';
}
if (context->sockets & XDG_APP_CONTEXT_SOCKET_X11)
{
g_debug ("Allowing x11 access");
xdg_app_run_add_x11_args (argv_array);
}
if ((g_key_file_get_boolean (metakey, "Environment", "wayland", NULL) || g_strv_contains (allow, "wayland")) &&
!g_strv_contains (forbid, "wayland"))
if (context->sockets & XDG_APP_CONTEXT_SOCKET_WAYLAND)
{
g_debug ("Allowing wayland access");
xdg_app_run_add_wayland_args (argv_array);
}
if ((g_key_file_get_boolean (metakey, "Environment", "pulseaudio", NULL) || g_strv_contains (allow, "pulseaudio")) &&
!g_strv_contains (forbid, "pulseaudio"))
if (context->sockets & XDG_APP_CONTEXT_SOCKET_PULSEAUDIO)
{
g_debug ("Allowing pulseaudio access");
xdg_app_run_add_pulseaudio_args (argv_array);
}
if ((g_key_file_get_boolean (metakey, "Environment", "system-dbus", NULL) || g_strv_contains (allow, "system-dbus")) &&
!g_strv_contains (forbid, "system-dbus"))
{
g_debug ("Allowing system-dbus access");
xdg_app_run_add_system_dbus_args (argv_array, dbus_proxy_argv);
}
unrestricted_session_bus =
(g_key_file_get_boolean (metakey, "Environment", "session-dbus", NULL) || g_strv_contains (allow, "session-dbus")) &&
!g_strv_contains (forbid, "session-dbus");
unrestricted_session_bus = (context->sockets & XDG_APP_CONTEXT_SOCKET_SESSION_BUS) != 0;
if (unrestricted_session_bus)
g_debug ("Allowing session-dbus access");
if (xdg_app_run_add_session_dbus_args (argv_array, dbus_proxy_argv, unrestricted_session_bus) &&
!unrestricted_session_bus && dbus_proxy_argv)
{
xdg_app_add_bus_filters (dbus_proxy_argv, app_id,
runtime_metakey, metakey);
xdg_app_add_bus_filters (dbus_proxy_argv, app_id, context);
}
if ((g_key_file_get_boolean (metakey, "Environment", "session-dbus", NULL) || g_strv_contains (allow, "session-dbus")) &&
!g_strv_contains (forbid, "session-dbus"))
if (context->sockets & XDG_APP_CONTEXT_SOCKET_SYSTEM_BUS)
{
g_debug ("Allowing session-dbus access");
g_debug ("Allowing system-dbus access");
xdg_app_run_add_system_dbus_args (argv_array, dbus_proxy_argv);
}
g_assert (sizeof(opts) > i);
@@ -1157,6 +1089,11 @@ xdg_app_run_add_environment_args (GPtrArray *argv_array,
opts[i++] = 0;
g_ptr_array_add (argv_array, g_strdup (opts));
}
/* TODO:
Handle persistent
Handle detailed filesystems
*/
}
static const struct {const char *env; const char *val;} default_exports[] = {
@@ -1277,29 +1214,26 @@ xdg_app_run_apply_env_appid (char **envp,
}
char **
xdg_app_run_apply_env_vars (char **envp, GKeyFile *metakey)
xdg_app_run_apply_env_vars (char **envp, XdgAppContext *context)
{
glnx_strfreev char **keys = NULL;
gsize i, keys_count;
GHashTableIter iter;
gpointer key, value;
keys = g_key_file_get_keys (metakey, "Environment Vars", &keys_count, NULL);
if (keys)
g_hash_table_iter_init (&iter, context->env_vars);
while (g_hash_table_iter_next (&iter, &key, &value))
{
for (i = 0; i < keys_count; i++)
{
const char *key = keys[i];
g_autofree char *value = g_key_file_get_string (metakey, "Environment Vars", key, NULL);
const char *var = key;
const char *val = value;
/* We special case LD_LIBRARY_PATH to avoid passing it top
the helper */
if (strcmp (key, "LD_LIBRARY_PATH") == 0)
key = "_LD_LIBRARY_PATH";
/* We special case LD_LIBRARY_PATH to avoid passing it top
the helper */
if (strcmp (var, "LD_LIBRARY_PATH") == 0)
var = "_LD_LIBRARY_PATH";
if (value)
envp = g_environ_setenv (envp, key, value, TRUE);
else
envp = g_environ_unsetenv (envp, key);
}
if (val && val[0] != 0)
envp = g_environ_setenv (envp, var, val, TRUE);
else
envp = g_environ_unsetenv (envp, var);
}
return envp;

View File

@@ -49,21 +49,16 @@ void xdg_app_context_save_metadata (XdgAppContext
G_DEFINE_AUTOPTR_CLEANUP_FUNC(XdgAppContext, xdg_app_context_free)
gboolean xdg_app_run_verify_environment_keys (const char **keys,
GError **error);
void xdg_app_run_add_environment_args (GPtrArray *argv_array,
GPtrArray *dbus_proxy_argv,
const char *app_id,
GKeyFile *runtime_metakey,
GKeyFile *metakey,
const char **allow,
const char **forbid);
XdgAppContext *context);
char ** xdg_app_run_get_minimal_env (gboolean devel);
char ** xdg_app_run_apply_env_default (char **envp);
char ** xdg_app_run_apply_env_appid (char **envp,
GFile *app_dir);
char ** xdg_app_run_apply_env_vars (char **envp,
GKeyFile *metakey);
XdgAppContext *context);
GFile *xdg_app_get_data_dir (const char *app_id);
GFile *xdg_app_ensure_data_dir (const char *app_id,