diff -Nru flatpak-0.11.7/app/flatpak-builtins-add-remote.c flatpak-0.11.8.3/app/flatpak-builtins-add-remote.c --- flatpak-0.11.7/app/flatpak-builtins-add-remote.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-add-remote.c 2018-05-30 13:58:57.000000000 +0100 @@ -31,7 +31,7 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" static gboolean opt_no_gpg_verify; static gboolean opt_do_gpg_verify; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-bundle.c flatpak-0.11.8.3/app/flatpak-builtins-build-bundle.c --- flatpak-0.11.7/app/flatpak-builtins-build-bundle.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-bundle.c 2018-05-30 13:58:57.000000000 +0100 @@ -34,9 +34,9 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-oci-registry.h" -#include "flatpak-chain-input-stream.h" +#include "flatpak-utils-private.h" +#include "flatpak-oci-registry-private.h" +#include "flatpak-chain-input-stream-private.h" #include "flatpak-builtins-utils.h" #include @@ -143,7 +143,7 @@ * figure out the type. The uint32 is basically a random value, but * it ensures we have both zero and high bits sets, so we don't get * sniffed as text. Also, the last 01 can be used as a version - * later. Furthermore, the use of an uint32 lets use detect + * later. Furthermore, the use of an uint32 lets us detect * byteorder issues. */ g_variant_builder_add (&metadata_builder, "{sv}", "flatpak", diff -Nru flatpak-0.11.7/app/flatpak-builtins-build.c flatpak-0.11.8.3/app/flatpak-builtins-build.c --- flatpak-0.11.7/app/flatpak-builtins-build.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build.c 2018-06-11 15:11:45.000000000 +0100 @@ -31,8 +31,8 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static gboolean opt_runtime; static char *opt_build_dir; @@ -409,6 +409,15 @@ extension_point = g_build_filename (bare_extension_point, x_subdir_suffix, NULL); } + app_context = flatpak_app_compute_permissions (metakey, + runtime_metakey, + error); + if (app_context == NULL) + return FALSE; + + flatpak_context_allow_host_fs (app_context); + flatpak_context_merge (app_context, arg_context); + minimal_envp = flatpak_run_get_minimal_env (TRUE, FALSE); bwrap = flatpak_bwrap_new (minimal_envp); flatpak_bwrap_add_args (bwrap, flatpak_get_bwrap (), NULL); @@ -421,6 +430,8 @@ if (custom_usr) run_flags |= FLATPAK_RUN_FLAG_WRITABLE_ETC; + run_flags |= flatpak_context_get_run_flags (app_context); + /* Unless manually specified, we disable dbus proxy */ if (!flatpak_context_get_needs_session_bus_proxy (arg_context)) run_flags |= FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY; @@ -494,15 +505,6 @@ "--bind", flatpak_file_get_path_cached (var_tmp), "/var/tmp", NULL); - app_context = flatpak_app_compute_permissions (metakey, - runtime_metakey, - error); - if (app_context == NULL) - return FALSE; - - flatpak_context_allow_host_fs (app_context); - flatpak_context_merge (app_context, arg_context); - flatpak_run_apply_env_vars (bwrap, app_context); if (is_app) @@ -556,6 +558,9 @@ NULL); } + if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error)) + return FALSE; + flatpak_bwrap_add_args (bwrap, command, NULL); flatpak_bwrap_append_argsv (bwrap, &argv[rest_argv_start + 2], diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-commit-from.c flatpak-0.11.8.3/app/flatpak-builtins-build-commit-from.c --- flatpak-0.11.7/app/flatpak-builtins-build-commit-from.c 2018-04-12 15:09:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-commit-from.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "parse-datetime.h" static char *opt_src_repo; @@ -58,7 +58,7 @@ { "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the commit with"), N_("KEY-ID") }, { "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") }, { "end-of-life", 0, 0, G_OPTION_ARG_STRING, &opt_endoflife, N_("Mark build as end-of-life"), N_("REASON") }, - { "timestamp", 0, 0, G_OPTION_ARG_STRING, &opt_timestamp, "Override the timestamp of the commit", N_("TIMESTAMP") }, + { "timestamp", 0, 0, G_OPTION_ARG_STRING, &opt_timestamp, N_("Override the timestamp of the commit (NOW for current time)"), N_("TIMESTAMP") }, { NULL } }; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-export.c flatpak-0.11.8.3/app/flatpak-builtins-build-export.c --- flatpak-0.11.7/app/flatpak-builtins-build-export.c 2018-04-19 10:33:54.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-export.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "parse-datetime.h" static char *opt_subject; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-finish.c flatpak-0.11.8.3/app/flatpak-builtins-build-finish.c --- flatpak-0.11.7/app/flatpak-builtins-build-finish.c 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-finish.c 2018-05-30 13:58:57.000000000 +0100 @@ -31,9 +31,9 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-context.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-context-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static char *opt_command; static char *opt_require_version; @@ -654,7 +654,7 @@ case 1: /* DIR */ flatpak_complete_options (completion, global_entries); flatpak_complete_options (completion, options); - flatpak_context_complete (arg_context, completion); + flatpak_complete_context (completion); flatpak_complete_dir (completion); break; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-import-bundle.c flatpak-0.11.8.3/app/flatpak-builtins-build-import-bundle.c --- flatpak-0.11.7/app/flatpak-builtins-build-import-bundle.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-import-bundle.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,8 +30,8 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-oci-registry.h" +#include "flatpak-utils-private.h" +#include "flatpak-oci-registry-private.h" static char *opt_ref; static gboolean opt_oci = FALSE; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-init.c flatpak-0.11.8.3/app/flatpak-builtins-build-init.c --- flatpak-0.11.7/app/flatpak-builtins-build-init.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-init.c 2018-05-30 13:58:57.000000000 +0100 @@ -31,8 +31,8 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static char *opt_arch; static char *opt_var; diff -Nru flatpak-0.11.7/app/flatpak-builtins-build-sign.c flatpak-0.11.8.3/app/flatpak-builtins-build-sign.c --- flatpak-0.11.7/app/flatpak-builtins-build-sign.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-build-sign.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" static char *opt_arch; static gboolean opt_runtime; diff -Nru flatpak-0.11.7/app/flatpak-builtins-config.c flatpak-0.11.8.3/app/flatpak-builtins-config.c --- flatpak-0.11.7/app/flatpak-builtins-config.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-config.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "common/flatpak-dir.h" +#include "common/flatpak-dir-private.h" static gboolean opt_get; static gboolean opt_set; diff -Nru flatpak-0.11.7/app/flatpak-builtins-document-export.c flatpak-0.11.8.3/app/flatpak-builtins-document-export.c --- flatpak-0.11.7/app/flatpak-builtins-document-export.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-document-export.c 2018-05-30 13:58:57.000000000 +0100 @@ -29,13 +29,13 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-document-dbus.h" +#include "flatpak-document-dbus-generated.h" #include #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static gboolean opt_unique = FALSE; static gboolean opt_transient = FALSE; diff -Nru flatpak-0.11.7/app/flatpak-builtins-document-info.c flatpak-0.11.8.3/app/flatpak-builtins-document-info.c --- flatpak-0.11.7/app/flatpak-builtins-document-info.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-document-info.c 2018-05-30 13:58:57.000000000 +0100 @@ -29,13 +29,13 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-document-dbus.h" +#include "flatpak-document-dbus-generated.h" #include #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static GOptionEntry options[] = { { NULL } diff -Nru flatpak-0.11.7/app/flatpak-builtins-document-list.c flatpak-0.11.8.3/app/flatpak-builtins-document-list.c --- flatpak-0.11.7/app/flatpak-builtins-document-list.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-document-list.c 2018-05-30 13:58:57.000000000 +0100 @@ -29,11 +29,11 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-document-dbus.h" +#include "flatpak-document-dbus-generated.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static GOptionEntry options[] = { { NULL } diff -Nru flatpak-0.11.7/app/flatpak-builtins-document-unexport.c flatpak-0.11.8.3/app/flatpak-builtins-document-unexport.c --- flatpak-0.11.7/app/flatpak-builtins-document-unexport.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-document-unexport.c 2018-05-30 13:58:57.000000000 +0100 @@ -29,13 +29,13 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-document-dbus.h" +#include "flatpak-document-dbus-generated.h" #include #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static GOptionEntry options[] = { { NULL } diff -Nru flatpak-0.11.7/app/flatpak-builtins-enter.c flatpak-0.11.8.3/app/flatpak-builtins-enter.c --- flatpak-0.11.7/app/flatpak-builtins-enter.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-enter.c 2018-05-30 13:58:57.000000000 +0100 @@ -32,9 +32,9 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-dbus.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-dbus-generated.h" +#include "flatpak-run-private.h" static GOptionEntry options[] = { diff -Nru flatpak-0.11.7/app/flatpak-builtins.h flatpak-0.11.8.3/app/flatpak-builtins.h --- flatpak-0.11.7/app/flatpak-builtins.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins.h 2018-06-11 14:52:37.000000000 +0100 @@ -24,8 +24,9 @@ #include #include -#include "flatpak-utils.h" -#include "flatpak-dir.h" +#include "flatpak-complete.h" +#include "flatpak-utils-private.h" +#include "flatpak-dir-private.h" G_BEGIN_DECLS @@ -90,6 +91,7 @@ BUILTINPROTO (repo) BUILTINPROTO (config) BUILTINPROTO (search) +BUILTINPROTO (repair) #undef BUILTINPROTO diff -Nru flatpak-0.11.7/app/flatpak-builtins-info.c flatpak-0.11.8.3/app/flatpak-builtins-info.c --- flatpak-0.11.7/app/flatpak-builtins-info.c 2018-04-13 14:53:31.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-info.c 2018-06-11 14:52:37.000000000 +0100 @@ -30,9 +30,9 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-builtins-utils.h" -#include "flatpak-run.h" +#include "flatpak-run-private.h" static gboolean opt_user; static gboolean opt_system; @@ -41,8 +41,11 @@ static gboolean opt_show_origin; static gboolean opt_show_size; static gboolean opt_show_metadata; +static gboolean opt_show_runtime; +static gboolean opt_show_sdk; static gboolean opt_show_permissions; static gboolean opt_show_extensions; +static gboolean opt_show_location; static char *opt_arch; static char **opt_installations; static char *opt_file_access; @@ -57,9 +60,12 @@ { "show-origin", 'o', 0, G_OPTION_ARG_NONE, &opt_show_origin, N_("Show origin"), NULL }, { "show-size", 's', 0, G_OPTION_ARG_NONE, &opt_show_size, N_("Show size"), NULL }, { "show-metadata", 'm', 0, G_OPTION_ARG_NONE, &opt_show_metadata, N_("Show metadata"), NULL }, + { "show-runtime", 0, 0, G_OPTION_ARG_NONE, &opt_show_runtime, N_("Show runtime"), NULL }, + { "show-sdk", 0, 0, G_OPTION_ARG_NONE, &opt_show_sdk, N_("Show sdk"), NULL }, { "show-permissions", 'M', 0, G_OPTION_ARG_NONE, &opt_show_permissions, N_("Show permissions"), NULL }, { "file-access", 0, 0, G_OPTION_ARG_FILENAME, &opt_file_access, N_("Query file access"), N_("PATH") }, { "show-extensions", 'e', 0, G_OPTION_ARG_NONE, &opt_show_extensions, N_("Show extensions"), NULL }, + { "show-location", 'l', 0, G_OPTION_ARG_NONE, &opt_show_location, N_("Show location"), NULL }, { NULL } }; @@ -172,7 +178,8 @@ metakey = flatpak_deploy_get_metadata (deploy); - if (opt_show_ref || opt_show_origin || opt_show_commit || opt_show_size || opt_show_metadata || opt_show_permissions || opt_file_access) + if (opt_show_ref || opt_show_origin || opt_show_commit || opt_show_size || opt_show_metadata || opt_show_permissions || + opt_file_access || opt_show_location || opt_show_runtime || opt_show_sdk) friendly = FALSE; if (friendly) @@ -241,8 +248,11 @@ if (strcmp (parts[0], "app") == 0) { g_autofree char *runtime = NULL; + g_autofree char *sdk = NULL; runtime = g_key_file_get_string (metakey, "Application", "runtime", error); g_print ("%s%s%s %s\n", on, _("Runtime:"), off, runtime ? runtime : "-"); + sdk = g_key_file_get_string (metakey, "Application", "sdk", error); + g_print ("%s%s%s %s\n", on, _("Sdk:"), off, sdk ? sdk : "-"); } if (subpaths[0] != NULL) { @@ -279,6 +289,36 @@ g_print ("%s", formatted); } + if (opt_show_location) + { + maybe_print_space (&first); + g_print ("%s", path); + } + + if (opt_show_runtime) + { + g_autofree char *runtime = NULL; + maybe_print_space (&first); + + if (strcmp (parts[0], "app") == 0) + runtime = g_key_file_get_string (metakey, "Application", "runtime", NULL); + else + runtime = g_key_file_get_string (metakey, "Runtime", "runtime", NULL); + g_print ("%s", runtime ? runtime : "-"); + } + + if (opt_show_sdk) + { + g_autofree char *sdk = NULL; + maybe_print_space (&first); + + if (strcmp (parts[0], "app") == 0) + sdk = g_key_file_get_string (metakey, "Application", "sdk", NULL); + else + sdk = g_key_file_get_string (metakey, "Runtime", "sdk", NULL); + g_print ("%s", sdk ? sdk : "-"); + } + if (!first) g_print ("\n"); @@ -398,7 +438,7 @@ context = g_option_context_new (""); if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, - FLATPAK_BUILTIN_FLAG_ALL_DIRS, &dirs, NULL, NULL)) + FLATPAK_BUILTIN_FLAG_ALL_DIRS|FLATPAK_BUILTIN_FLAG_OPTIONAL_REPO, &dirs, NULL, NULL)) return FALSE; kinds = FLATPAK_KINDS_APP | FLATPAK_KINDS_RUNTIME; diff -Nru flatpak-0.11.7/app/flatpak-builtins-info-remote.c flatpak-0.11.8.3/app/flatpak-builtins-info-remote.c --- flatpak-0.11.7/app/flatpak-builtins-info-remote.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-info-remote.c 2018-06-11 14:52:37.000000000 +0100 @@ -31,7 +31,7 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-table-printer.h" static char *opt_arch; @@ -43,6 +43,8 @@ static gboolean opt_show_parent; static gboolean opt_show_metadata; static gboolean opt_log; +static gboolean opt_show_runtime; +static gboolean opt_show_sdk; static GOptionEntry options[] = { { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to install for"), N_("ARCH") }, @@ -54,6 +56,8 @@ { "show-commit", 'c', 0, G_OPTION_ARG_NONE, &opt_show_commit, N_("Show commit"), NULL }, { "show-parent", 'p', 0, G_OPTION_ARG_NONE, &opt_show_parent, N_("Show parent"), NULL }, { "show-metadata", 'm', 0, G_OPTION_ARG_NONE, &opt_show_metadata, N_("Show metadata"), NULL }, + { "show-runtime", 0, 0, G_OPTION_ARG_NONE, &opt_show_runtime, N_("Show runtime"), NULL }, + { "show-sdk", 0, 0, G_OPTION_ARG_NONE, &opt_show_sdk, N_("Show sdk"), NULL }, { NULL } }; @@ -160,9 +164,11 @@ off = FLATPAK_ANSI_BOLD_OFF; /* bold off */ } - if (opt_show_ref || opt_show_commit || opt_show_parent || opt_show_metadata) + if (opt_show_ref || opt_show_commit || opt_show_parent || opt_show_metadata || opt_show_runtime || opt_show_sdk) friendly = FALSE; + parts = g_strsplit (ref, "/", 0); + if (friendly) { g_variant_get (commit_v, "(a{sv}aya(say)&s&stayay)", NULL, NULL, NULL, @@ -192,7 +198,6 @@ if (g_variant_lookup (commit_metadata, "xa.download-size", "t", &download_size)) download_size = GUINT64_FROM_BE (download_size); - parts = g_strsplit (ref, "/", 0); formatted_installed_size = g_format_size (installed_size); formatted_download_size = g_format_size (download_size); formatted_timestamp = format_timestamp (timestamp); @@ -212,8 +217,11 @@ if (strcmp (parts[0], "app") == 0 && metakey != NULL) { g_autofree char *runtime = NULL; + g_autofree char *sdk = NULL; runtime = g_key_file_get_string (metakey, "Application", "runtime", error); g_print ("%s%s%s %s\n", on, _("Runtime:"), off, runtime ? runtime : "-"); + sdk = g_key_file_get_string (metakey, "Application", "sdk", error); + g_print ("%s%s%s %s\n", on, _("Sdk:"), off, sdk ? sdk : "-"); } if (opt_log) @@ -260,8 +268,19 @@ do { g_autofree char *p = ostree_commit_get_parent (c_v); + g_autoptr(GVariant) c_m = g_variant_get_child_value (c_v, 0); gboolean first = TRUE; + g_variant_lookup (c_m, "xa.metadata", "&s", &xa_metadata); + if (xa_metadata == NULL) + g_printerr (_("Warning: Commit %s has no flatpak metadata\n"), c); + else + { + metakey = g_key_file_new (); + if (!g_key_file_load_from_data (metakey, xa_metadata, -1, 0, error)) + return FALSE; + } + if (opt_show_ref) { maybe_print_space (&first); @@ -280,19 +299,41 @@ g_print ("%s", p ? p : "-"); } + if (opt_show_runtime) + { + g_autofree char *runtime = NULL; + maybe_print_space (&first); + + if (metakey) + { + if (strcmp (parts[0], "app") == 0) + runtime = g_key_file_get_string (metakey, "Application", "runtime", NULL); + else + runtime = g_key_file_get_string (metakey, "Runtime", "runtime", NULL); + } + g_print ("%s", runtime ? runtime : "-"); + } + + if (opt_show_sdk) + { + g_autofree char *sdk = NULL; + maybe_print_space (&first); + + if (metakey) + { + if (strcmp (parts[0], "app") == 0) + sdk = g_key_file_get_string (metakey, "Application", "sdk", NULL); + else + sdk = g_key_file_get_string (metakey, "Runtime", "sdk", NULL); + } + g_print ("%s", sdk ? sdk : "-"); + } + if (!first) g_print ("\n"); if (opt_show_metadata) - { - g_autoptr(GVariant) c_m = NULL; - c_m = g_variant_get_child_value (c_v, 0); - g_variant_lookup (c_m, "xa.metadata", "&s", &xa_metadata); - if (xa_metadata == NULL) - g_printerr (_("Warning: Commit %s has no flatpak metadata\n"), c); - else - g_print ("%s", xa_metadata); - } + g_print ("%s", xa_metadata); g_free (c); c = g_steal_pointer (&p); diff -Nru flatpak-0.11.7/app/flatpak-builtins-install.c flatpak-0.11.8.3/app/flatpak-builtins-install.c --- flatpak-0.11.7/app/flatpak-builtins-install.c 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-install.c 2018-05-30 13:58:57.000000000 +0100 @@ -33,10 +33,10 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-transaction.h" -#include "flatpak-utils.h" -#include "lib/flatpak-error.h" -#include "flatpak-chain-input-stream.h" +#include "flatpak-cli-transaction.h" +#include "flatpak-utils-private.h" +#include "flatpak-error.h" +#include "flatpak-chain-input-stream-private.h" static char *opt_arch; static char **opt_gpg_file; @@ -287,13 +287,21 @@ if (!flatpak_dir_ensure_repo (dir, cancellable, error)) return FALSE; - transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy, - opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall); + transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error); + if (transaction == NULL) + return FALSE; + + flatpak_transaction_set_no_pull (transaction, opt_no_pull); + flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); + flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); + flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps); + flatpak_transaction_set_disable_related (transaction, opt_no_related); + flatpak_transaction_set_reinstall (transaction, opt_reinstall); if (!flatpak_transaction_add_install_bundle (transaction, file, gpg_data, error)) return FALSE; - if (!flatpak_transaction_run (transaction, TRUE, cancellable, error)) + if (!flatpak_cli_transaction_run (transaction, cancellable, error)) return FALSE; return TRUE; @@ -441,16 +449,21 @@ slash = strchr (ref, '/'); g_print (_("Installing: %s\n"), slash + 1); - transaction = flatpak_transaction_new (clone, opt_yes, opt_no_pull, opt_no_deploy, - opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall); - - if (!flatpak_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error)) + transaction = flatpak_cli_transaction_new (clone, opt_yes, TRUE, error); + if (transaction == NULL) return FALSE; - if (!flatpak_transaction_update_metadata (transaction, FALSE, cancellable, error)) + flatpak_transaction_set_no_pull (transaction, opt_no_pull); + flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); + flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); + flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps); + flatpak_transaction_set_disable_related (transaction, opt_no_related); + flatpak_transaction_set_reinstall (transaction, opt_reinstall); + + if (!flatpak_cli_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error)) return FALSE; - if (!flatpak_transaction_run (transaction, TRUE, cancellable, error)) + if (!flatpak_cli_transaction_run (transaction, cancellable, error)) return FALSE; return TRUE; @@ -520,8 +533,16 @@ default_branch = flatpak_dir_get_remote_default_branch (dir, remote); kinds = flatpak_kinds_from_bools (opt_app, opt_runtime); - transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy, - opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall); + transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error); + if (transaction == NULL) + return FALSE; + + flatpak_transaction_set_no_pull (transaction, opt_no_pull); + flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); + flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); + flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps); + flatpak_transaction_set_disable_related (transaction, opt_no_related); + flatpak_transaction_set_reinstall (transaction, opt_reinstall); for (i = 0; i < n_prefs; i++) { @@ -548,15 +569,11 @@ if (ref == NULL) return FALSE; - if (!flatpak_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error)) + if (!flatpak_cli_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error)) return FALSE; } - if (!opt_no_pull && - !flatpak_transaction_update_metadata (transaction, FALSE, cancellable, error)) - return FALSE; - - if (!flatpak_transaction_run (transaction, TRUE, cancellable, error)) + if (!flatpak_cli_transaction_run (transaction, cancellable, error)) return FALSE; return TRUE; diff -Nru flatpak-0.11.7/app/flatpak-builtins-list.c flatpak-0.11.8.3/app/flatpak-builtins-list.c --- flatpak-0.11.7/app/flatpak-builtins-list.c 2018-04-13 14:48:04.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-list.c 2018-06-11 14:52:37.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-table-printer.h" static gboolean opt_show_details; @@ -313,7 +313,7 @@ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_ALL_DIRS, + FLATPAK_BUILTIN_FLAG_ALL_DIRS|FLATPAK_BUILTIN_FLAG_OPTIONAL_REPO, &dirs, cancellable, error)) return FALSE; diff -Nru flatpak-0.11.7/app/flatpak-builtins-list-remotes.c flatpak-0.11.8.3/app/flatpak-builtins-list-remotes.c --- flatpak-0.11.7/app/flatpak-builtins-list-remotes.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-list-remotes.c 2018-06-11 14:52:37.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-table-printer.h" static gboolean opt_show_details; @@ -54,7 +54,7 @@ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS|FLATPAK_BUILTIN_FLAG_OPTIONAL_REPO, &dirs, cancellable, error)) return FALSE; if (argc > 1) diff -Nru flatpak-0.11.7/app/flatpak-builtins-ls-remote.c flatpak-0.11.8.3/app/flatpak-builtins-ls-remote.c --- flatpak-0.11.7/app/flatpak-builtins-ls-remote.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-ls-remote.c 2018-05-30 13:58:57.000000000 +0100 @@ -31,7 +31,7 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-table-printer.h" static gboolean opt_show_details; diff -Nru flatpak-0.11.7/app/flatpak-builtins-make-current.c flatpak-0.11.8.3/app/flatpak-builtins-make-current.c --- flatpak-0.11.7/app/flatpak-builtins-make-current.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-make-current.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" static char *opt_arch; diff -Nru flatpak-0.11.7/app/flatpak-builtins-override.c flatpak-0.11.8.3/app/flatpak-builtins-override.c --- flatpak-0.11.7/app/flatpak-builtins-override.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-override.c 2018-05-30 13:58:57.000000000 +0100 @@ -32,8 +32,8 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-run-private.h" static GOptionEntry options[] = { { NULL } @@ -125,7 +125,7 @@ case 1: /* NAME */ flatpak_complete_options (completion, global_entries); flatpak_complete_options (completion, options); - flatpak_context_complete (arg_context, completion); + flatpak_complete_context (completion); for (i = 0; i < dirs->len; i++) { diff -Nru flatpak-0.11.7/app/flatpak-builtins-repair.c flatpak-0.11.8.3/app/flatpak-builtins-repair.c --- flatpak-0.11.7/app/flatpak-builtins-repair.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-repair.c 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,425 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include +#include +#include +#include + +#include + +#include "libglnx/libglnx.h" + +#include "flatpak-builtins.h" +#include "flatpak-builtins-utils.h" +#include "flatpak-utils-private.h" +#include "flatpak-table-printer.h" +#include "flatpak-error.h" +#include "flatpak-cli-transaction.h" + +static GOptionEntry options[] = { + { NULL } +}; + +typedef enum { + FSCK_STATUS_OK, + FSCK_STATUS_HAS_MISSING_OBJECTS, + FSCK_STATUS_HAS_INVALID_OBJECTS, +} FsckStatus; + +static FsckStatus +fsck_one_object (OstreeRepo *repo, + const char *checksum, + OstreeObjectType objtype, + gboolean allow_missing) +{ + g_autoptr(GError) local_error = NULL; + + if (!ostree_repo_fsck_object (repo, objtype, checksum, NULL, &local_error)) + { + if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + g_clear_error (&local_error); + if (!allow_missing) + g_printerr (_("Object missing: %s.%s\n"), checksum, + ostree_object_type_to_string (objtype)); + return FSCK_STATUS_HAS_MISSING_OBJECTS; + } + else + { + g_printerr (_("%s, deleting object\n"), local_error->message); + (void) ostree_repo_delete_object (repo, objtype, checksum, NULL, NULL); + return FSCK_STATUS_HAS_INVALID_OBJECTS; + } + } + + return FSCK_STATUS_OK; +} + +/* This is used for leaf object types */ +static FsckStatus +fsck_leaf_object (OstreeRepo *repo, + const char *checksum, + OstreeObjectType objtype, + GHashTable *object_status_cache) +{ + g_autoptr(GVariant) key = NULL; + gpointer cached_status; + FsckStatus status = 0; + + key = g_variant_ref_sink (ostree_object_name_serialize (checksum, objtype)); + + if (g_hash_table_lookup_extended (object_status_cache, key, NULL, &cached_status)) + { + status = GPOINTER_TO_INT (cached_status); + } + else + { + status = fsck_one_object (repo, checksum, objtype, FALSE); + g_hash_table_insert (object_status_cache, g_steal_pointer (&key), GINT_TO_POINTER (status)); + } + + return status; +} + + +static FsckStatus +fsck_dirtree (OstreeRepo *repo, + gboolean partial, + const char *checksum, + GHashTable *object_status_cache) +{ + OstreeRepoCommitIterResult iterres; + g_autoptr(GError) local_error = NULL; + FsckStatus status = 0; + g_autoptr(GVariant) key = NULL; + g_autoptr(GVariant) dirtree = NULL; + gpointer cached_status; + ostree_cleanup_repo_commit_traverse_iter + OstreeRepoCommitTraverseIter iter = { 0, }; + + key = g_variant_ref_sink (ostree_object_name_serialize (checksum, OSTREE_OBJECT_TYPE_DIR_TREE)); + if (g_hash_table_lookup_extended (object_status_cache, key, NULL, &cached_status)) + return GPOINTER_TO_INT (cached_status); + + /* First verify the dirtree itself */ + status = fsck_one_object (repo, checksum, OSTREE_OBJECT_TYPE_DIR_TREE, partial); + + if (status == FSCK_STATUS_OK) + { + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_DIR_TREE, checksum, + &dirtree, &local_error) || + !ostree_repo_commit_traverse_iter_init_dirtree (&iter, repo, dirtree, 0, &local_error)) + { + g_printerr (_("Can't load object %s: %s\n"), checksum, local_error->message); + g_clear_error (&local_error); + status = MAX (status, FSCK_STATUS_HAS_INVALID_OBJECTS); + } + else + { + /* Then its children, recursively */ + while (TRUE) + { + iterres = ostree_repo_commit_traverse_iter_next (&iter, NULL, &local_error); + if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_ERROR) + { + /* Some internal error in the dir-object */ + g_print ("%s\n", local_error->message); + g_clear_error (&local_error); + status = MAX (status, FSCK_STATUS_HAS_INVALID_OBJECTS); + break; + } + else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_END) + break; + else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_FILE) + { + char *name; + char *checksum; + FsckStatus file_status; + + ostree_repo_commit_traverse_iter_get_file (&iter, &name, &checksum); + file_status = fsck_leaf_object (repo, checksum, OSTREE_OBJECT_TYPE_FILE, object_status_cache); + status = MAX (status, file_status); + } + else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_DIR) + { + char *name; + char *meta_checksum; + char *dirtree_checksum; + FsckStatus meta_status; + FsckStatus dirtree_status; + + ostree_repo_commit_traverse_iter_get_dir (&iter, &name, &dirtree_checksum, &meta_checksum); + + meta_status = fsck_leaf_object (repo, meta_checksum, OSTREE_OBJECT_TYPE_DIR_META, object_status_cache); + status = MAX (status, meta_status); + + dirtree_status = fsck_dirtree (repo, partial, dirtree_checksum, object_status_cache); + + status = MAX (status, dirtree_status); + } + else + g_assert_not_reached (); + } + } + } + + g_hash_table_insert (object_status_cache, g_steal_pointer (&key), GINT_TO_POINTER (status)); + return status; +} + +static FsckStatus +fsck_commit (OstreeRepo *repo, + const char *checksum, + GHashTable *object_status_cache) +{ + g_autoptr(GError) local_error = NULL; + g_autoptr(GVariant) commit = NULL; + g_autoptr(GVariant) dirtree_csum_bytes = NULL; + g_autofree char *dirtree_checksum = NULL; + g_autoptr(GVariant) meta_csum_bytes = NULL; + g_autofree char *meta_checksum = NULL; + OstreeRepoCommitState commitstate = 0; + FsckStatus status, dirtree_status, meta_status; + gboolean partial; + + status = fsck_one_object (repo, checksum, OSTREE_OBJECT_TYPE_COMMIT, FALSE); + if (status != FSCK_STATUS_OK) + return status; + + if (!ostree_repo_load_commit (repo, checksum, &commit, &commitstate, &local_error)) + { + g_print ("%s\n", local_error->message); + g_clear_error (&local_error); + return FSCK_STATUS_HAS_INVALID_OBJECTS; + } + + partial = (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) != 0; + + g_variant_get_child (commit, 7, "@ay", &meta_csum_bytes); + meta_checksum = ostree_checksum_from_bytes (ostree_checksum_bytes_peek (meta_csum_bytes)); + + meta_status = fsck_leaf_object (repo, meta_checksum, OSTREE_OBJECT_TYPE_DIR_META, object_status_cache); + status = MAX (status, meta_status); + + g_variant_get_child (commit, 6, "@ay", &dirtree_csum_bytes); + dirtree_checksum = ostree_checksum_from_bytes (ostree_checksum_bytes_peek (dirtree_csum_bytes)); + + dirtree_status = fsck_dirtree (repo, partial, dirtree_checksum, object_status_cache); + status = MAX (status, dirtree_status); + + /* Its ok for partial commits to have missing objects */ + if (status == FSCK_STATUS_HAS_MISSING_OBJECTS && partial) + status = FSCK_STATUS_OK; + + return status; +} + +static void +transaction_add_local_ref (FlatpakDir *dir, + FlatpakTransaction *transaction, + const char *ref) +{ + g_autoptr(GVariant) deploy_data = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree char *repo_checksum = NULL; + const char *origin; + const char **subpaths; + + deploy_data = flatpak_dir_get_deploy_data (dir, ref, NULL, &local_error); + if (deploy_data == NULL) + { + if (!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED)) + g_printerr (_("Problems loading data for %s: %s\n"), ref, local_error->message); + g_clear_error (&local_error); + return; + } + + origin = flatpak_deploy_data_get_origin (deploy_data); + subpaths = flatpak_deploy_data_get_subpaths (deploy_data); + + repo_checksum = flatpak_dir_read_latest (dir, origin, ref, NULL, NULL, NULL); + if (repo_checksum == NULL) + { + if (!flatpak_transaction_add_install (transaction, origin, ref, subpaths, &local_error)) + { + g_printerr (_("Error reinstalling %s: %s\n"), ref, local_error->message); + g_clear_error (&local_error); + } + } +} + + +gboolean +flatpak_builtin_repair (int argc, char **argv, GCancellable *cancellable, GError **error) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(GPtrArray) dirs = NULL; + FlatpakDir *dir = NULL; + g_autoptr(GHashTable) all_refs = NULL; + g_autoptr(GHashTable) invalid_refs = NULL; + g_autoptr(GHashTable) object_status_cache = NULL; + g_auto(GStrv) app_refs = NULL; + g_auto(GStrv) runtime_refs = NULL; + g_autoptr(FlatpakTransaction) transaction = NULL; + OstreeRepo *repo; + int i; + + context = g_option_context_new (_(" REMOTE REF - Show information about an application or runtime in a remote")); + g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); + + if (!flatpak_option_context_parse (context, options, &argc, &argv, + FLATPAK_BUILTIN_FLAG_ONE_DIR, &dirs, cancellable, error)) + return FALSE; + + + dir = g_ptr_array_index (dirs, 0); + + if (!flatpak_dir_ensure_repo (dir, cancellable, error)) + return FALSE; + + repo = flatpak_dir_get_repo (dir); + + /* + * Try to repair a flatpak directory: + * + Scan all locally available refs + * + remove ref that don't correspond to a deployed ref + * + Verify the commits they point to and all object they reference: + * + Remove any invalid objects + * + Note any missing objects + * + Any refs that had invalid object, or non-partial refs that had missing objects are removed + * + prune (depth=0) all object not references by a ref, which gets rid of any possibly invalid non-scanned objects + * + Enumerate all deployed refs: + * + if they are not in the repo (or is partial for a non-subdir deploy), re-install them (pull + deploy) + */ + + object_status_cache = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, + (GDestroyNotify)g_variant_unref, NULL); + + invalid_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + /* Validate that the commit for each ref is available */ + if (!ostree_repo_list_refs (repo, NULL, &all_refs, + cancellable, error)) + return FALSE; + + GLNX_HASH_TABLE_FOREACH_KV(all_refs, const char *, refspec, const char *, checksum) + { + g_autofree char *remote = NULL; + g_autofree char *ref_name = NULL; + FsckStatus status; + + if (!ostree_parse_refspec (refspec, &remote, &ref_name, error)) + return FALSE; + + /* Does this look like a regular ref? */ + if (g_str_has_prefix (ref_name, "app/") || g_str_has_prefix (ref_name, "runtime/")) + { + g_autofree char *origin = flatpak_dir_get_origin (dir, ref_name, cancellable, NULL); + + /* If so, is it deployed, and from this remote? */ + if (remote == NULL || g_strcmp0 (origin, remote) != 0) + { + g_print (_("Removing non-deployed ref %s...\n"), refspec); + (void)ostree_repo_set_ref_immediate (repo, remote, ref_name, NULL, cancellable, NULL); + continue; + } + } + + g_print (_("Verifying %s...\n"), refspec); + + status = fsck_commit (repo, checksum, object_status_cache); + if (status != FSCK_STATUS_OK) + { + g_printerr (_("Deleting ref %s due to missing objects\n"), refspec); + (void)ostree_repo_set_ref_immediate (repo, remote, ref_name, NULL, cancellable, NULL); + } + } + + g_print (_("Pruning objects\n")); + + if (!flatpak_dir_prune (dir, cancellable, error)) + return FALSE; + + if (!flatpak_dir_list_refs (dir, "app", &app_refs, cancellable, NULL)) + return FALSE; + + if (!flatpak_dir_list_refs (dir, "runtime", &runtime_refs, cancellable, NULL)) + return FALSE; + + transaction = flatpak_cli_transaction_new (dir, TRUE, FALSE, error); + if (transaction == NULL) + return FALSE; + + flatpak_transaction_set_disable_dependencies (transaction, TRUE); + flatpak_transaction_set_disable_related (transaction, TRUE); + flatpak_transaction_set_reinstall (transaction, TRUE); + + for (i = 0; app_refs[i] != NULL; i++) + { + const char *ref = app_refs[i]; + + transaction_add_local_ref (dir, transaction, ref); + } + + for (i = 0; runtime_refs[i] != NULL; i++) + { + const char *ref = runtime_refs[i]; + + transaction_add_local_ref (dir, transaction, ref); + } + + if (!flatpak_transaction_is_empty (transaction)) + { + g_print (_("Reinstalling removed refs\n")); + if (!flatpak_cli_transaction_run (transaction, cancellable, error)) + return FALSE; + } + + return TRUE; +} + +gboolean +flatpak_complete_repair (FlatpakCompletion *completion) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(GPtrArray) dirs = NULL; + + context = g_option_context_new (""); + + if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, NULL, NULL)) + return FALSE; + + switch (completion->argc) + { + case 0: + case 1: /* REMOTE */ + flatpak_complete_options (completion, global_entries); + flatpak_complete_options (completion, options); + flatpak_complete_options (completion, user_entries); + + break; + } + + return TRUE; +} diff -Nru flatpak-0.11.7/app/flatpak-builtins-repo.c flatpak-0.11.8.3/app/flatpak-builtins-repo.c --- flatpak-0.11.7/app/flatpak-builtins-repo.c 2018-04-13 14:48:04.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-repo.c 2018-05-30 13:58:57.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-table-printer.h" static void diff -Nru flatpak-0.11.7/app/flatpak-builtins-repo-update.c flatpak-0.11.8.3/app/flatpak-builtins-repo-update.c --- flatpak-0.11.7/app/flatpak-builtins-repo-update.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-repo-update.c 2018-06-11 14:52:37.000000000 +0100 @@ -30,7 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-builtins-utils.h" static char *opt_title; @@ -281,7 +281,6 @@ GCancellable *cancellable, GError **error) { - g_autoptr(GMainContext) context = g_main_context_new (); g_autoptr(GHashTable) all_refs = NULL; g_autoptr(GHashTable) all_deltas_hash = NULL; g_autoptr(GHashTable) wanted_deltas_hash = NULL; @@ -292,6 +291,7 @@ g_autoptr(GVariantBuilder) parambuilder = NULL; g_autoptr(GVariant) params = NULL; int n_spawned_delta_generate = 0; + g_autoptr(GMainContextPopDefault) context = NULL; g_print ("Generating static deltas\n"); @@ -317,7 +317,7 @@ cancellable, error)) return FALSE; - g_main_context_push_thread_default (context); + context = flatpak_main_context_new_default (); g_hash_table_iter_init (&iter, all_refs); while (g_hash_table_iter_next (&iter, &key, &value)) @@ -342,7 +342,7 @@ if (!spawn_delete_generation (context, &n_spawned_delta_generate, repo, params, ref, NULL, commit, error)) - goto error; + return FALSE; } /* Mark this one as wanted */ @@ -368,7 +368,7 @@ if (!spawn_delete_generation (context, &n_spawned_delta_generate, repo, params, ref, parent_commit, commit, error)) - goto error; + return FALSE; } /* Mark parent-to-current as wanted */ @@ -392,8 +392,6 @@ while (n_spawned_delta_generate > 0) g_main_context_iteration (context, TRUE); - g_main_context_pop_thread_default (context); - *unwanted_deltas = g_ptr_array_new_with_free_func (g_free); for (i = 0; i < all_deltas->len; i++) { @@ -403,10 +401,6 @@ } return TRUE; - - error: - g_main_context_pop_thread_default (context); - return FALSE; } gboolean diff -Nru flatpak-0.11.7/app/flatpak-builtins-run.c flatpak-0.11.8.3/app/flatpak-builtins-run.c --- flatpak-0.11.7/app/flatpak-builtins-run.c 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-run.c 2018-05-30 13:58:57.000000000 +0100 @@ -32,10 +32,10 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" #include "flatpak-error.h" -#include "flatpak-dbus.h" -#include "flatpak-run.h" +#include "flatpak-dbus-generated.h" +#include "flatpak-run-private.h" static char *opt_arch; static char *opt_branch; @@ -230,7 +230,7 @@ case 1: /* NAME */ flatpak_complete_options (completion, global_entries); flatpak_complete_options (completion, options); - flatpak_context_complete (arg_context, completion); + flatpak_complete_context (completion); user_dir = flatpak_dir_get_user (); { diff -Nru flatpak-0.11.7/app/flatpak-builtins-search.c flatpak-0.11.8.3/app/flatpak-builtins-search.c --- flatpak-0.11.7/app/flatpak-builtins-search.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-search.c 2018-06-11 14:52:37.000000000 +0100 @@ -25,9 +25,9 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-dir.h" +#include "flatpak-dir-private.h" #include "flatpak-table-printer.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" static char *opt_arch; @@ -243,7 +243,8 @@ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS | FLATPAK_BUILTIN_FLAG_OPTIONAL_REPO, + &dirs, cancellable, error)) return FALSE; if (argc < 2) diff -Nru flatpak-0.11.7/app/flatpak-builtins-uninstall.c flatpak-0.11.8.3/app/flatpak-builtins-uninstall.c --- flatpak-0.11.7/app/flatpak-builtins-uninstall.c 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-uninstall.c 2018-06-11 14:52:37.000000000 +0100 @@ -31,7 +31,9 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" +#include "flatpak-cli-transaction.h" +#include #include "flatpak-error.h" static char *opt_arch; @@ -40,6 +42,9 @@ static gboolean opt_no_related; static gboolean opt_runtime; static gboolean opt_app; +static gboolean opt_all; +static gboolean opt_yes; +static gboolean opt_unused; static GOptionEntry options[] = { { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to uninstall"), N_("ARCH") }, @@ -48,6 +53,9 @@ { "force-remove", 0, 0, G_OPTION_ARG_NONE, &opt_force_remove, N_("Remove files even if running"), NULL }, { "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL }, { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL }, + { "all", 0, 0, G_OPTION_ARG_NONE, &opt_all, N_("Uninstall all"), NULL }, + { "unused", 0, 0, G_OPTION_ARG_NONE, &opt_unused, N_("Uninstall unused"), NULL }, + { "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL }, { NULL } }; @@ -102,6 +110,26 @@ return udir; } +static void +find_used_refs (FlatpakDir *dir, GHashTable *used_refs, const char *ref, const char *origin) +{ + g_autoptr(GPtrArray) related = NULL; + int i; + + g_hash_table_add (used_refs, g_strdup (ref)); + + related = flatpak_dir_find_local_related (dir, ref, origin, TRUE, NULL, NULL); + if (related == NULL) + return; + + for (i = 0; i < related->len; i++) + { + FlatpakRelated *rel = g_ptr_array_index (related, i); + + if (!rel->auto_prune) + g_hash_table_add (used_refs, g_strdup (rel->ref)); + } +} gboolean flatpak_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GError **error) @@ -111,8 +139,6 @@ char **prefs = NULL; int i, j, k, n_prefs; const char *default_branch = NULL; - FlatpakHelperUninstallFlags flags = 0; - g_autoptr(GPtrArray) related = NULL; FlatpakKinds kinds; FlatpakKinds kind; g_autoptr(GHashTable) uninstall_dirs = NULL; @@ -125,8 +151,14 @@ &dirs, cancellable, error)) return FALSE; - if (argc < 2) - return usage_error (context, _("Must specify at least one REF"), error); + if (argc < 2 && !opt_all && !opt_unused) + return usage_error (context, _("Must specify at least one REF, --unused or --all"), error); + + if (argc >= 2 && opt_all) + return usage_error (context, _("Must not specify REFs when using --all"), error); + + if (argc >= 2 && opt_unused) + return usage_error (context, _("Must not specify REFs when using --unused"), error); prefs = &argv[1]; n_prefs = argc - 1; @@ -141,144 +173,247 @@ kinds = flatpak_kinds_from_bools (opt_app, opt_runtime); uninstall_dirs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)uninstall_dir_free); - for (j = 0; j < n_prefs; j++) + if (opt_all) { - const char *pref = NULL; - FlatpakKinds matched_kinds; - g_autofree char *id = NULL; - g_autofree char *arch = NULL; - g_autofree char *branch = NULL; - g_autoptr(GError) local_error = NULL; - g_autoptr(GError) first_error = NULL; - g_autofree char *first_ref = NULL; - g_autofree char *origin = NULL; - g_autoptr(GPtrArray) dirs_with_ref = NULL; - UninstallDir *udir = NULL; + for (j = 0; j < dirs->len; j++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, j); + UninstallDir *udir = uninstall_dir_ensure (uninstall_dirs, dir); + g_auto(GStrv) app_refs = NULL; + g_auto(GStrv) runtime_refs = NULL; - pref = prefs[j]; + if (flatpak_dir_list_refs (dir, "app", &app_refs, NULL, NULL)) + { + for (k = 0; app_refs[k] != NULL; k++) + uninstall_dir_add_ref (udir, app_refs[k]); + } - if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, default_branch, - &matched_kinds, &id, &arch, &branch, error)) - return FALSE; + if (flatpak_dir_list_refs (dir, "runtime", &runtime_refs, NULL, NULL)) + { + for (k = 0; runtime_refs[k] != NULL; k++) + uninstall_dir_add_ref (udir, runtime_refs[k]); + } + } + } + else if (opt_unused) + { + gboolean found_something_to_uninstall = FALSE; - dirs_with_ref = g_ptr_array_new (); - for (k = 0; k < dirs->len; k++) + for (j = 0; j < dirs->len; j++) { - FlatpakDir *dir = g_ptr_array_index (dirs, k); - g_autofree char *ref = NULL; + FlatpakDir *dir = g_ptr_array_index (dirs, j); + UninstallDir *udir = uninstall_dir_ensure (uninstall_dirs, dir); + g_auto(GStrv) app_refs = NULL; + g_auto(GStrv) runtime_refs = NULL; + g_autoptr(GHashTable) used_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_autoptr(GHashTable) used_runtimes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - ref = flatpak_dir_find_installed_ref (dir, id, branch, arch, - kinds, &kind, &local_error); - if (ref == NULL) + if (!flatpak_dir_list_refs (dir, "app", &app_refs, NULL, NULL)) + continue; + + if (!flatpak_dir_list_refs (dir, "runtime", &runtime_refs, NULL, NULL)) + continue; + + for (i = 0; app_refs[i] != NULL; i++) { - if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED)) - { - if (first_error == NULL) - first_error = g_steal_pointer (&local_error); - g_clear_error (&local_error); - } - else + const char *ref = app_refs[i]; + g_autoptr(FlatpakDeploy) deploy = NULL; + g_autofree char *origin = NULL; + g_autofree char *runtime = NULL; + g_autoptr(GKeyFile) metakey = NULL; + g_auto(GStrv) parts = g_strsplit (ref, "/", -1); + + if (opt_arch != NULL && strcmp (parts[2], opt_arch) != 0) + continue; + + deploy = flatpak_dir_load_deployed (dir, ref, NULL, NULL, NULL); + if (deploy == NULL) + continue; + + origin = flatpak_dir_get_origin (dir, ref, NULL, NULL); + if (origin == NULL) + continue; + + find_used_refs (dir, used_refs, ref, origin); + + metakey = flatpak_deploy_get_metadata (deploy); + runtime = g_key_file_get_string (metakey, "Application", "runtime", NULL); + if (runtime) + g_hash_table_add (used_runtimes, g_steal_pointer (&runtime)); + } + + GLNX_HASH_TABLE_FOREACH(used_runtimes, const char *, runtime) + { + g_autofree char *runtime_ref = g_strconcat ("runtime/", runtime, NULL); + g_autoptr(FlatpakDeploy) deploy = NULL; + g_autofree char *origin = NULL; + g_autofree char *sdk = NULL; + g_autoptr(GKeyFile) metakey = NULL; + + deploy = flatpak_dir_load_deployed (dir, runtime_ref, NULL, NULL, NULL); + if (deploy == NULL) + continue; + + origin = flatpak_dir_get_origin (dir, runtime_ref, NULL, NULL); + if (origin == NULL) + continue; + + find_used_refs (dir, used_refs, runtime_ref, origin); + + metakey = flatpak_deploy_get_metadata (deploy); + sdk = g_key_file_get_string (metakey, "Runtime", "sdk", NULL); + if (sdk) { - g_propagate_error (error, g_steal_pointer (&local_error)); - return FALSE; + g_autofree char *sdk_ref = g_strconcat ("runtime/", sdk, NULL); + g_autofree char *sdk_origin = flatpak_dir_get_origin (dir, sdk_ref, NULL, NULL); + if (sdk_origin) + find_used_refs (dir, used_refs, sdk_ref, sdk_origin); } } - else + + for (i = 0; runtime_refs[i] != NULL; i++) + { + const char *ref = runtime_refs[i]; + g_auto(GStrv) parts = g_strsplit (ref, "/", -1); + + if (opt_arch != NULL && strcmp (parts[2], opt_arch) != 0) + continue; + + if (!g_hash_table_contains (used_refs, ref)) + uninstall_dir_add_ref (udir, ref); + } + + if (udir->refs->len > 0) { - g_ptr_array_add (dirs_with_ref, dir); - if (first_ref == NULL) - first_ref = g_strdup (ref); + g_print (_("Uninstalling from %s:\n"), flatpak_dir_get_name (dir)); + g_ptr_array_sort (udir->refs, flatpak_strcmp0_ptr); + for (i = 0; i < udir->refs->len; i++) + g_print (" %s\n", (char *)udir->refs->pdata[i]); + found_something_to_uninstall = TRUE; } } - if (dirs_with_ref->len == 0) + if (!found_something_to_uninstall) { - g_assert (first_error != NULL); - /* No match anywhere, return the first NOT_INSTALLED error */ - g_propagate_error (error, g_steal_pointer (&first_error)); - return FALSE; + g_print (_("Nothing unused to uninstall\n")); + return TRUE; } - if (dirs_with_ref->len > 1) + if (!opt_yes && + !flatpak_yes_no_prompt (_("Is this ok?"))) + return TRUE; + } + else + { + for (j = 0; j < n_prefs; j++) { - g_autoptr(GString) dir_names = g_string_new (""); - for (k = 0; k < dirs_with_ref->len; k++) - { - FlatpakDir *dir = g_ptr_array_index (dirs_with_ref, k); - g_autofree char *dir_name = flatpak_dir_get_name (dir); - if (k > 0) - g_string_append (dir_names, ", "); - g_string_append (dir_names, dir_name); - } - - return flatpak_fail (error, - _("Ref ‘%s’ found in multiple installations: %s. You must specify one."), - pref, dir_names->str); - } + const char *pref = NULL; + FlatpakKinds matched_kinds; + g_autofree char *id = NULL; + g_autofree char *arch = NULL; + g_autofree char *branch = NULL; + g_autoptr(GError) local_error = NULL; + g_autoptr(GError) first_error = NULL; + g_autofree char *first_ref = NULL; + g_autoptr(GPtrArray) dirs_with_ref = NULL; + UninstallDir *udir = NULL; - udir = uninstall_dir_ensure (uninstall_dirs, g_ptr_array_index (dirs_with_ref, 0)); + pref = prefs[j]; - g_assert (first_ref); + if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, default_branch, + &matched_kinds, &id, &arch, &branch, error)) + return FALSE; - uninstall_dir_add_ref (udir, first_ref); + dirs_with_ref = g_ptr_array_new (); + for (k = 0; k < dirs->len; k++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, k); + g_autofree char *ref = NULL; - /* TODO: when removing runtimes, look for apps that use it, require --force */ + ref = flatpak_dir_find_installed_ref (dir, id, branch, arch, + kinds, &kind, &local_error); + if (ref == NULL) + { + if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED)) + { + if (first_error == NULL) + first_error = g_steal_pointer (&local_error); + g_clear_error (&local_error); + } + else + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + else + { + g_ptr_array_add (dirs_with_ref, dir); + if (first_ref == NULL) + first_ref = g_strdup (ref); + } + } - if (opt_no_related) - continue; + if (dirs_with_ref->len == 0) + { + g_assert (first_error != NULL); + /* No match anywhere, return the first NOT_INSTALLED error */ + g_propagate_error (error, g_steal_pointer (&first_error)); + return FALSE; + } - origin = flatpak_dir_get_origin (udir->dir, first_ref, NULL, NULL); - if (origin == NULL) - continue; + if (dirs_with_ref->len > 1) + { + g_autoptr(GString) dir_names = g_string_new (""); + for (k = 0; k < dirs_with_ref->len; k++) + { + FlatpakDir *dir = g_ptr_array_index (dirs_with_ref, k); + g_autofree char *dir_name = flatpak_dir_get_name (dir); + if (k > 0) + g_string_append (dir_names, ", "); + g_string_append (dir_names, dir_name); + } - related = flatpak_dir_find_local_related (udir->dir, first_ref, origin, - NULL, &local_error); - if (related == NULL) - { - g_printerr (_("Warning: Problem looking for related refs: %s\n"), - local_error->message); - continue; - } + return flatpak_fail (error, + _("Ref ‘%s’ found in multiple installations: %s. You must specify one."), + pref, dir_names->str); + } - for (i = 0; i < related->len; i++) - { - FlatpakRelated *rel = g_ptr_array_index (related, i); - g_autoptr(GVariant) deploy_data = NULL; + udir = uninstall_dir_ensure (uninstall_dirs, g_ptr_array_index (dirs_with_ref, 0)); - if (!rel->delete) - continue; + g_assert (first_ref); - deploy_data = flatpak_dir_get_deploy_data (udir->dir, rel->ref, NULL, NULL); - if (deploy_data != NULL) - uninstall_dir_add_ref (udir, rel->ref); + uninstall_dir_add_ref (udir, first_ref); } } - if (opt_keep_ref) - flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF; - if (opt_force_remove) - flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE; - GLNX_HASH_TABLE_FOREACH_V (uninstall_dirs, UninstallDir *, udir) { - g_autofree char *dir_name = flatpak_dir_get_name (udir->dir); + g_autoptr(FlatpakTransaction) transaction = NULL; + + transaction = flatpak_cli_transaction_new (udir->dir, FALSE, TRUE, error); + if (transaction == NULL) + return FALSE; + + flatpak_transaction_set_disable_prune (transaction, opt_keep_ref); + flatpak_transaction_set_force_uninstall (transaction, opt_force_remove); + + /* This disables the remote metadata update, since uninstall is a local-only op */ + flatpak_transaction_set_no_pull (transaction, TRUE); for (i = 0; i < udir->refs->len; i++) { const char *ref = (char *)g_ptr_array_index (udir->refs, i); - const char *pref = strchr (ref, '/') + 1; - - g_print (_("Uninstalling: %s from %s\n"), pref, dir_name); - if (!flatpak_dir_uninstall (udir->dir, ref, flags, - cancellable, error)) + if (!flatpak_transaction_add_uninstall (transaction, ref, error)) return FALSE; } - if (!opt_keep_ref) - flatpak_dir_prune (udir->dir, cancellable, NULL); + if (!flatpak_cli_transaction_run (transaction, cancellable, error)) + return FALSE; } + return TRUE; } diff -Nru flatpak-0.11.7/app/flatpak-builtins-update.c flatpak-0.11.8.3/app/flatpak-builtins-update.c --- flatpak-0.11.7/app/flatpak-builtins-update.c 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-update.c 2018-05-30 13:58:57.000000000 +0100 @@ -31,8 +31,8 @@ #include "flatpak-builtins.h" #include "flatpak-builtins-utils.h" -#include "flatpak-transaction.h" -#include "flatpak-utils.h" +#include "flatpak-cli-transaction.h" +#include "flatpak-utils-private.h" #include "flatpak-error.h" static char *opt_arch; @@ -106,13 +106,20 @@ n_prefs = 1; } - transactions = g_ptr_array_new_with_free_func ((GDestroyNotify)flatpak_transaction_free); + transactions = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); for (k = 0; k < dirs->len; k++) { - FlatpakTransaction *transaction = flatpak_transaction_new (g_ptr_array_index (dirs, k), - opt_yes, opt_no_pull, opt_no_deploy, - opt_no_static_deltas, !opt_no_deps, !opt_no_related, FALSE); + FlatpakTransaction *transaction = flatpak_cli_transaction_new (g_ptr_array_index (dirs, k), opt_yes, FALSE, error); + if (transaction == NULL) + return FALSE; + + flatpak_transaction_set_no_pull (transaction, opt_no_pull); + flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); + flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); + flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps); + flatpak_transaction_set_disable_related (transaction, opt_no_related); + g_ptr_array_add (transactions, transaction); } @@ -220,14 +227,9 @@ { FlatpakTransaction *transaction = g_ptr_array_index (transactions, k); - if (!flatpak_transaction_is_empty (transaction)) - { - if (!flatpak_transaction_update_metadata (transaction, n_prefs == 0, cancellable, error)) - return FALSE; - - if (!flatpak_transaction_run (transaction, FALSE, cancellable, error)) - return FALSE; - } + if (!flatpak_transaction_is_empty (transaction) && + !flatpak_cli_transaction_run (transaction, cancellable, error)) + return FALSE; } if (n_prefs == 0) diff -Nru flatpak-0.11.7/app/flatpak-builtins-utils.c flatpak-0.11.8.3/app/flatpak-builtins-utils.c --- flatpak-0.11.7/app/flatpak-builtins-utils.c 2018-04-30 13:33:48.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-utils.c 2018-05-30 13:58:57.000000000 +0100 @@ -24,10 +24,10 @@ #include -#include "flatpak-chain-input-stream.h" +#include "flatpak-chain-input-stream-private.h" #include "flatpak-builtins-utils.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" gboolean diff -Nru flatpak-0.11.7/app/flatpak-builtins-utils.h flatpak-0.11.8.3/app/flatpak-builtins-utils.h --- flatpak-0.11.7/app/flatpak-builtins-utils.h 2018-04-04 16:31:23.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-builtins-utils.h 2018-05-30 13:58:57.000000000 +0100 @@ -23,8 +23,8 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-utils.h" -#include "flatpak-dir.h" +#include "flatpak-utils-private.h" +#include "flatpak-dir-private.h" /* Appstream data expires after a day */ #define FLATPAK_APPSTREAM_TTL 86400 diff -Nru flatpak-0.11.7/app/flatpak-cli-transaction.c flatpak-0.11.8.3/app/flatpak-cli-transaction.c --- flatpak-0.11.7/app/flatpak-cli-transaction.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-cli-transaction.c 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,436 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-cli-transaction.h" +#include "flatpak-transaction-private.h" +#include "flatpak-installation-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-error.h" +#include +#include + + +struct _FlatpakCliTransaction { + FlatpakTransaction parent; + + gboolean disable_interaction; + gboolean stop_on_first_error; + gboolean is_user; + GError *first_operation_error; + + gboolean progress_initialized; + int progress_n_columns; + int progress_last_width; +}; + +struct _FlatpakCliTransactionClass { + FlatpakCliTransactionClass parent_class; +}; + +G_DEFINE_TYPE (FlatpakCliTransaction, flatpak_cli_transaction, FLATPAK_TYPE_TRANSACTION); + +static int +choose_remote_for_ref (FlatpakTransaction *transaction, + const char *for_ref, + const char *runtime_ref, + const char * const *remotes) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction); + int n_remotes = g_strv_length ((char **)remotes); + int chosen = -1; + const char *pref; + int i; + + pref = strchr (for_ref, '/') + 1; + + if (self->disable_interaction) + { + g_print (_("Required runtime for %s (%s) found in remote %s\n"), + pref, runtime_ref, remotes[0]); + chosen = 0; + } + else if (n_remotes == 1) + { + g_print (_("Required runtime for %s (%s) found in remote %s\n"), + pref, runtime_ref, remotes[0]); + if (flatpak_yes_no_prompt (_("Do you want to install it?"))) + chosen = 0; + } + else + { + g_print (_("Required runtime for %s (%s) found in remotes: %s\n"), + pref, runtime_ref, remotes[0]); + for (i = 0; remotes[i] != NULL; i++) + { + g_print ("%d) %s\n", i + 1, remotes[i]); + } + chosen = flatpak_number_prompt (0, n_remotes, _("Which do you want to install (0 to abort)?")); + chosen -= 1; /* convert from base-1 to base-0 (and -1 to abort) */ + } + + return chosen; +} + +static char * +op_type_to_string (FlatpakTransactionOperationType operation_type) +{ + switch (operation_type) + { + case FLATPAK_TRANSACTION_OPERATION_INSTALL: + return _("install"); + case FLATPAK_TRANSACTION_OPERATION_UPDATE: + return _("update"); + case FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: + return _("install bundle"); + case FLATPAK_TRANSACTION_OPERATION_UNINSTALL: + return _("uninstall"); + default: + return "Unknown type"; /* Should not happen */ + } +} + +#define BAR_LENGTH 20 +#define BAR_CHARS " -=#" + + +static void +progress_changed_cb (FlatpakTransactionProgress *progress, + gpointer data) +{ + FlatpakCliTransaction *cli = data; + g_autoptr(GString) str = g_string_new (""); + int i; + int n_full, remainder, partial; + int width, padded_width; + + guint percent = flatpak_transaction_progress_get_progress (progress); + g_autofree char *status = flatpak_transaction_progress_get_status (progress); + + if (!cli->progress_initialized) + { + struct winsize w; + cli->progress_n_columns = 80; + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w) == 0) + cli->progress_n_columns = w.ws_col; + cli->progress_last_width = 0; + cli->progress_initialized = TRUE; + } + + g_string_append (str, "["); + + n_full = (BAR_LENGTH * percent) / 100; + remainder = percent - (n_full * 100 / BAR_LENGTH); + partial = (remainder * strlen(BAR_CHARS) * BAR_LENGTH) / 100; + + for (i = 0; i < n_full; i++) + g_string_append_c (str, BAR_CHARS[strlen(BAR_CHARS)-1]); + + if (i < BAR_LENGTH) + { + g_string_append_c (str, BAR_CHARS[partial]); + i++; + } + + for (; i < BAR_LENGTH; i++) + g_string_append (str, " "); + + g_string_append (str, "] "); + g_string_append (str, status); + + g_print ("\r"); + width = MIN (strlen (str->str), cli->progress_n_columns); + padded_width = MAX (cli->progress_last_width, width); + cli->progress_last_width = width; + g_print ("%-*.*s", padded_width, padded_width, str->str); +} + +static void +progress_done (FlatpakTransaction *transaction) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction); + + if (self->progress_initialized) + g_print("\n"); +} + +static void +new_operation (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + const char *bundle_path, + FlatpakTransactionOperationType operation_type, + FlatpakTransactionProgress *progress) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction); + const char *pref; + g_autofree char *bundle_basename = NULL; + + pref = strchr (ref, '/') + 1; + + switch (operation_type) + { + case FLATPAK_TRANSACTION_OPERATION_INSTALL: + if (self->is_user) + g_print (_("Installing for user: %s from %s\n"), pref, remote); + else + g_print (_("Installing: %s from %s\n"), pref, remote); + break; + case FLATPAK_TRANSACTION_OPERATION_UPDATE: + if (self->is_user) + g_print (_("Updating for user: %s from %s\n"), pref, remote); + else + g_print (_("Updating: %s from %s\n"), pref, remote); + break; + case FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: + { + bundle_basename = g_path_get_basename (bundle_path); + if (self->is_user) + g_print (_("Installing for user: %s from bundle %s\n"), pref, bundle_basename); + else + g_print (_("Installing: %s from bundle %s\n"), pref, bundle_basename); + } + break; + case FLATPAK_TRANSACTION_OPERATION_UNINSTALL: + if (self->is_user) + g_print (_("Uninstalling for user: %s\n"), pref); + else + g_print (_("Uninstalling: %s\n"), pref); + break; + default: + g_assert_not_reached (); + break; + } + + self->progress_initialized = FALSE; + g_signal_connect (progress, "changed", G_CALLBACK (progress_changed_cb), self); + flatpak_transaction_progress_set_update_frequency (progress, FLATPAK_CLI_UPDATE_FREQUENCY); + +} + +static void +operation_done (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + FlatpakTransactionOperationType operation_type, + const char *commit, + FlatpakTransactionResult details) +{ + g_autofree char *short_commit = g_strndup (commit, 12); + + progress_done (transaction); + + if (operation_type != FLATPAK_TRANSACTION_OPERATION_UNINSTALL) + { + if (details & FLATPAK_TRANSACTION_RESULT_NO_CHANGE) + g_print (_("No updates.\n")); + else + g_print (_("Now at %s.\n"), short_commit); + } +} + +static gboolean +operation_error (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + FlatpakTransactionOperationType operation_type, + GError *error, + FlatpakTransactionErrorDetails detail) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction); + const char *pref; + + progress_done (transaction); + + pref = strchr (ref, '/') + 1; + + if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_SKIPPED)) + { + g_printerr ("%s", error->message); + return TRUE; + } + + if (detail & FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL) + { + g_printerr (_("Warning: Failed to %s %s: %s\n"), + op_type_to_string (operation_type), pref, error->message); + } + else + { + if (self->first_operation_error == NULL) + g_propagate_prefixed_error (&self->first_operation_error, + g_error_copy (error), + _("Failed to %s %s: "), + op_type_to_string (operation_type), pref); + + if (self->stop_on_first_error) + return FALSE; + + g_printerr (_("Error: Failed to %s %s: %s\n"), + op_type_to_string (operation_type), pref, error->message); + } + + return TRUE; /* Continue */ +} + +static void +end_of_lifed (FlatpakTransaction *transaction, + const char *ref, + const char *reason, + const char *rebase) +{ + if (rebase) + { + g_printerr (_("Warning: %s is end-of-life, in preference of %s\n"), ref, rebase); + } + else if (reason) + { + g_printerr (_("Warning: %s is end-of-life, with reason: %s\n"), ref, reason); + } +} + +static void +flatpak_cli_transaction_finalize (GObject *object) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (object); + + if (self->first_operation_error) + g_error_free (self->first_operation_error); + + G_OBJECT_CLASS (flatpak_cli_transaction_parent_class)->finalize (object); +} + +static void +flatpak_cli_transaction_init (FlatpakCliTransaction *self) +{ +} + +static void +flatpak_cli_transaction_class_init (FlatpakCliTransactionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + FlatpakTransactionClass *transaction_class = FLATPAK_TRANSACTION_CLASS (klass); + + object_class->finalize = flatpak_cli_transaction_finalize; + transaction_class->new_operation = new_operation; + transaction_class->operation_done = operation_done; + transaction_class->operation_error = operation_error; + transaction_class->choose_remote_for_ref = choose_remote_for_ref; + transaction_class->end_of_lifed = end_of_lifed; +} + +FlatpakTransaction * +flatpak_cli_transaction_new (FlatpakDir *dir, + gboolean disable_interaction, + gboolean stop_on_first_error, + GError **error) +{ + g_autoptr(FlatpakInstallation) installation = NULL; + g_autoptr(FlatpakCliTransaction) self = NULL; + + installation = flatpak_installation_new_for_dir (dir, NULL, error); + if (installation == NULL) + return NULL; + + self = g_initable_new (FLATPAK_TYPE_CLI_TRANSACTION, + NULL, error, + "installation", installation, + NULL); + if (self == NULL) + return NULL; + + self->disable_interaction = disable_interaction; + self->stop_on_first_error = stop_on_first_error; + self->is_user = flatpak_dir_is_user (dir); + + return (FlatpakTransaction *)g_steal_pointer (&self); +} + +gboolean +flatpak_cli_transaction_add_install (FlatpakTransaction *transaction, + const char *remote, + const char *ref, + const char **subpaths, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + + if (!flatpak_transaction_add_install (transaction, remote, ref, subpaths, &local_error)) + { + if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) + { + g_printerr (_("Skipping: %s\n"), local_error->message); + return TRUE; + } + + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + return TRUE; +} + + +gboolean +flatpak_cli_transaction_run (FlatpakTransaction *transaction, + GCancellable *cancellable, + GError **error) +{ + FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction); + g_autoptr(GError) local_error = NULL; + gboolean res; + + res = flatpak_transaction_run (transaction, cancellable, &local_error); + + + /* If we got some weird error (i.e. not ABORTED because we chose to abort + on an error, report that */ + if (!res && + !g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED)) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + if (self->first_operation_error) + { + /* We always want to return an error if there was some kind of operation error, + as that causes the main CLI to return an error status. */ + + if (self->stop_on_first_error) + { + /* For the install/stop_on_first_error we return the first operation error, + as we have not yet printed it. */ + + g_propagate_error (error, g_steal_pointer (&self->first_operation_error)); + return FALSE; + } + else + { + /* For updates/!stop_on_first_error we already printed all errors so we make up + a different one. */ + + return flatpak_fail (error, _("There were one or more errors")); + } + } + + return TRUE; +} diff -Nru flatpak-0.11.7/app/flatpak-cli-transaction.h flatpak-0.11.8.3/app/flatpak-cli-transaction.h --- flatpak-0.11.7/app/flatpak-cli-transaction.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-cli-transaction.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,45 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_CLI_TRANSACTION_H__ +#define __FLATPAK_CLI_TRANSACTION_H__ + +#include "flatpak-transaction.h" +#include "flatpak-dir-private.h" + +#define FLATPAK_TYPE_CLI_TRANSACTION flatpak_cli_transaction_get_type () +G_DECLARE_FINAL_TYPE (FlatpakCliTransaction, flatpak_cli_transaction, FLATPAK, CLI_TRANSACTION, FlatpakTransaction) + +FlatpakTransaction *flatpak_cli_transaction_new (FlatpakDir *dir, + gboolean disable_interaction, + gboolean stop_on_first_error, + GError **error); + +gboolean flatpak_cli_transaction_add_install (FlatpakTransaction *self, + const char *remote, + const char *ref, + const char **subpaths, + GError **error); + +gboolean flatpak_cli_transaction_run (FlatpakTransaction *transaction, + GCancellable *cancellable, + GError **error); + +#endif /* __FLATPAK_CLI_TRANSACTION_H__ */ diff -Nru flatpak-0.11.7/app/flatpak-complete.c flatpak-0.11.8.3/app/flatpak-complete.c --- flatpak-0.11.7/app/flatpak-complete.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-complete.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,520 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-complete.h" +#include "flatpak-utils-private.h" + +/* Uncomment to get debug traces in /tmp/flatpak-completion-debug.txt (nice + * to not have it interfere with stdout/stderr) + */ +#if 0 +void +flatpak_completion_debug (const gchar *format, ...) +{ + va_list var_args; + gchar *s; + static FILE *f = NULL; + + va_start (var_args, format); + s = g_strdup_vprintf (format, var_args); + if (f == NULL) + f = fopen ("/tmp/flatpak-completion-debug.txt", "a+"); + fprintf (f, "%s\n", s); + fflush (f); + g_free (s); +} +#else +void +flatpak_completion_debug (const gchar *format, ...) +{ +} +#endif + +static gboolean +is_word_separator (char c) +{ + return g_ascii_isspace (c); +} + +void +flatpak_complete_file (FlatpakCompletion *completion, + const char *file_type) +{ + flatpak_completion_debug ("completing FILE"); + g_print ("%s\n", file_type); +} + +void +flatpak_complete_dir (FlatpakCompletion *completion) +{ + flatpak_completion_debug ("completing DIR"); + g_print ("%s\n", "__FLATPAK_DIR"); +} + +void +flatpak_complete_word (FlatpakCompletion *completion, + char *format, ...) +{ + va_list args; + const char *rest; + const char *shell_cur; + const char *shell_cur_end; + g_autofree char *string = NULL; + + g_return_if_fail (format != NULL); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + va_start (args, format); + string = g_strdup_vprintf (format, args); + va_end (args); +#pragma GCC diagnostic pop + + if (!g_str_has_prefix (string, completion->cur)) + return; + + shell_cur = completion->shell_cur ? completion->shell_cur : ""; + + rest = string + strlen (completion->cur); + + shell_cur_end = shell_cur + strlen(shell_cur); + while (shell_cur_end > shell_cur && + rest > string && + shell_cur_end[-1] == rest[-1] && + /* I'm not sure exactly what bash is doing here with =, but this seems to work... */ + shell_cur_end[-1] != '=') + { + rest--; + shell_cur_end--; + } + + flatpak_completion_debug ("completing word: '%s' (%s)", string, rest); + + g_print ("%s\n", rest); +} + +void +flatpak_complete_ref (FlatpakCompletion *completion, + OstreeRepo *repo) +{ + g_autoptr(GHashTable) refs = NULL; + flatpak_completion_debug ("completing REF"); + + if (ostree_repo_list_refs (repo, + NULL, + &refs, NULL, NULL)) + { + GHashTableIter hashiter; + gpointer hashkey, hashvalue; + + g_hash_table_iter_init (&hashiter, refs); + while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))) + { + const char *ref = (const char *)hashkey; + if (!(g_str_has_prefix (ref, "runtime/") || + g_str_has_prefix (ref, "app/"))) + continue; + flatpak_complete_word (completion, "%s", ref); + } + } +} + +static int +find_current_element (const char *str) +{ + int count = 0; + + if (g_str_has_prefix (str, "app/")) + str += strlen ("app/"); + else if (g_str_has_prefix (str, "runtime/")) + str += strlen ("runtime/"); + + while (str != NULL && count <= 3) + { + str = strchr (str, '/'); + count++; + if (str != NULL) + str = str + 1; + } + + return count; +} + +void +flatpak_complete_partial_ref (FlatpakCompletion *completion, + FlatpakKinds kinds, + const char *only_arch, + FlatpakDir *dir, + const char *remote) +{ + FlatpakKinds matched_kinds; + const char *pref; + g_autofree char *id = NULL; + g_autofree char *arch = NULL; + g_autofree char *branch = NULL; + g_auto(GStrv) refs = NULL; + int element; + const char *cur_parts[4] = { NULL }; + g_autoptr(GError) error = NULL; + int i; + + pref = completion->cur; + element = find_current_element (pref); + + flatpak_split_partial_ref_arg_novalidate (pref, kinds, + NULL, NULL, + &matched_kinds, &id, &arch, &branch); + + cur_parts[1] = id; + cur_parts[2] = arch ? arch : ""; + cur_parts[3] = branch ? branch : ""; + + if (remote) + { + refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], + (element > 1) ? id : NULL, + (element > 3) ? branch : NULL, + (element > 2 )? arch : only_arch, + matched_kinds, NULL, &error); + } + else + { + refs = flatpak_dir_find_installed_refs (dir, + (element > 1) ? id : NULL, + (element > 3) ? branch : NULL, + (element > 2 )? arch : only_arch, + matched_kinds, &error); + } + if (refs == NULL) + flatpak_completion_debug ("find refs error: %s", error->message); + for (i = 0; refs != NULL && refs[i] != NULL; i++) + { + int j; + g_autoptr(GString) comp = NULL; + g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL); + if (parts == NULL) + continue; + + if (!g_str_has_prefix (parts[element], cur_parts[element])) + continue; + + if (flatpak_id_has_subref_suffix (parts[element])) + { + char *last_dot = strrchr (parts[element], '.'); + + if (last_dot == NULL) + continue; /* Shouldn't really happen */ + + /* Only complete to subrefs is fully matching real part. + * For example, only match org.foo.Bar.Sources for + * "org.foo.Bar", "org.foo.Bar." or "org.foo.Bar.S", but + * not for "org.foo" or other shorter prefixes. + */ + if (strncmp (parts[element], cur_parts[element], last_dot - parts[element] - 1) != 0) + continue; + } + + comp = g_string_new (pref); + g_string_append (comp, parts[element] + strlen (cur_parts[element])); + + /* Only complete on the last part if the user explicitly adds a / */ + if (element >= 2) + { + for (j = element + 1; j < 4; j++) + { + g_string_append (comp, "/"); + g_string_append (comp, parts[j]); + } + } + + flatpak_complete_word (completion, "%s", comp->str); + } +} + +static gboolean +switch_already_in_line (FlatpakCompletion *completion, + GOptionEntry *entry) +{ + guint i = 0; + guint line_part_len = 0; + + for (; i < completion->original_argc; ++i) + { + line_part_len = strlen (completion->original_argv[i]); + if (line_part_len > 2 && + g_strcmp0 (&completion->original_argv[i][2], entry->long_name) == 0) + return TRUE; + + if (line_part_len == 2 && + completion->original_argv[i][1] == entry->short_name) + return TRUE; + } + + return FALSE; +} + +static gboolean +should_filter_out_option_from_completion (FlatpakCompletion *completion, + GOptionEntry *entry) +{ + switch (entry->arg) + { + case G_OPTION_ARG_NONE: + case G_OPTION_ARG_STRING: + case G_OPTION_ARG_INT: + case G_OPTION_ARG_FILENAME: + case G_OPTION_ARG_DOUBLE: + case G_OPTION_ARG_INT64: + return switch_already_in_line (completion, entry); + default: + return FALSE; + } +} + +void +flatpak_complete_options (FlatpakCompletion *completion, + GOptionEntry *entries) +{ + GOptionEntry *e = entries; + int i; + + while (e->long_name != NULL) + { + if (e->arg_description) + { + g_autofree char *prefix = g_strdup_printf ("--%s=", e->long_name); + + if (g_str_has_prefix (completion->cur, prefix)) + { + if (strcmp (e->arg_description, "ARCH") == 0) + { + const char *arches[] = {"i386", "x86_64", "aarch64", "arm"}; + for (i = 0; i < G_N_ELEMENTS (arches); i++) + flatpak_complete_word (completion, "%s%s ", prefix, arches[i]); + } + else if (strcmp (e->arg_description, "SHARE") == 0) + { + for (i = 0; flatpak_context_shares[i] != NULL; i++) + flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_shares[i]); + } + else if (strcmp (e->arg_description, "DEVICE") == 0) + { + for (i = 0; flatpak_context_devices[i] != NULL; i++) + flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_devices[i]); + } + else if (strcmp (e->arg_description, "FEATURE") == 0) + { + for (i = 0; flatpak_context_features[i] != NULL; i++) + flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_features[i]); + } + else if (strcmp (e->arg_description, "SOCKET") == 0) + { + for (i = 0; flatpak_context_sockets[i] != NULL; i++) + flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_sockets[i]); + } + else if (strcmp (e->arg_description, "FILE") == 0) + { + flatpak_complete_file (completion, "__FLATPAK_FILE"); + } + else + flatpak_complete_word (completion, "%s", prefix); + } + else + flatpak_complete_word (completion, "%s", prefix); + } + else + { + /* If this is just a switch, then don't add it multiple + * times */ + if (!should_filter_out_option_from_completion (completion, e)) { + flatpak_complete_word (completion, "--%s ", e->long_name); + } else { + flatpak_completion_debug ("switch --%s is already in line %s", e->long_name, completion->line); + } + } + + /* We may end up checking switch_already_in_line twice, but this is + * for simplicity's sake - the alternative solution would be to + * continue the loop early and have to increment e. */ + if (e->short_name != 0) + { + /* This is a switch, we may not want to add it */ + if (!e->arg_description) + { + if (!should_filter_out_option_from_completion (completion, e)) { + flatpak_complete_word (completion, "-%c ", e->short_name); + } else { + flatpak_completion_debug ("switch -%c is already in line %s", e->short_name, completion->line); + } + } + else + { + flatpak_complete_word (completion, "-%c ", e->short_name); + } + } + e++; + } +} + +void +flatpak_complete_context (FlatpakCompletion *completion) +{ + flatpak_complete_options (completion, flatpak_context_get_option_entries ()); +} + +static gchar * +pick_word_at (const char *s, + int cursor, + int *out_word_begins_at) +{ + int begin, end; + + if (s[0] == '\0') + { + if (out_word_begins_at != NULL) + *out_word_begins_at = -1; + return NULL; + } + + if (is_word_separator (s[cursor]) && ((cursor > 0 && is_word_separator(s[cursor-1])) || cursor == 0)) + { + if (out_word_begins_at != NULL) + *out_word_begins_at = cursor; + return g_strdup (""); + } + + while (!is_word_separator (s[cursor - 1]) && cursor > 0) + cursor--; + begin = cursor; + + end = begin; + while (!is_word_separator (s[end]) && s[end] != '\0') + end++; + + if (out_word_begins_at != NULL) + *out_word_begins_at = begin; + + return g_strndup (s + begin, end - begin); +} + +static gboolean +parse_completion_line_to_argv (const char *initial_completion_line, + FlatpakCompletion *completion) +{ + gboolean parse_result = g_shell_parse_argv (initial_completion_line, + &completion->original_argc, + &completion->original_argv, + NULL); + + /* Make a shallow copy of argv, which will be our "working set" */ + completion->argc = completion->original_argc; + completion->argv = g_memdup (completion->original_argv, + sizeof (gchar *) * (completion->original_argc + 1)); + + return parse_result; +} + +FlatpakCompletion * +flatpak_completion_new (const char *arg_line, + const char *arg_point, + const char *arg_cur) +{ + FlatpakCompletion *completion; + g_autofree char *initial_completion_line = NULL; + int _point; + char *endp; + int cur_begin; + int i; + + _point = strtol (arg_point, &endp, 10); + if (endp == arg_point || *endp != '\0') + return NULL; + + completion = g_new0 (FlatpakCompletion, 1); + completion->line = g_strdup (arg_line); + completion->shell_cur = g_strdup (arg_cur); + completion->point = _point; + + flatpak_completion_debug ("========================================"); + flatpak_completion_debug ("completion_point=%d", completion->point); + flatpak_completion_debug ("completion_shell_cur='%s'", completion->shell_cur); + flatpak_completion_debug ("----"); + flatpak_completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789"); + flatpak_completion_debug ("'%s'", completion->line); + flatpak_completion_debug (" %*s^", completion->point, ""); + + /* compute cur and prev */ + completion->prev = NULL; + completion->cur = pick_word_at (completion->line, completion->point, &cur_begin); + if (cur_begin > 0) + { + gint prev_end; + for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--) + { + if (!is_word_separator (completion->line[prev_end])) + { + completion->prev = pick_word_at (completion->line, prev_end, NULL); + break; + } + } + + initial_completion_line = g_strndup (completion->line, cur_begin); + } + else + initial_completion_line = g_strdup (""); + + flatpak_completion_debug ("'%s'", initial_completion_line); + flatpak_completion_debug ("----"); + + flatpak_completion_debug (" cur='%s'", completion->cur); + flatpak_completion_debug ("prev='%s'", completion->prev); + + if (!parse_completion_line_to_argv (initial_completion_line, + completion)) + { + /* it's very possible the command line can't be parsed (for + * example, missing quotes etc) - in that case, we just + * don't autocomplete at all + */ + flatpak_completion_free (completion); + return NULL; + } + + flatpak_completion_debug ("completion_argv %i:", completion->original_argc); + for (i = 0; i < completion->original_argc; i++) + flatpak_completion_debug (completion->original_argv[i]); + + flatpak_completion_debug ("----"); + + return completion; +} + +void +flatpak_completion_free (FlatpakCompletion *completion) +{ + g_free (completion->cur); + g_free (completion->prev); + g_free (completion->line); + g_free (completion->argv); + g_strfreev (completion->original_argv); + g_free (completion); +} diff -Nru flatpak-0.11.7/app/flatpak-complete.h flatpak-0.11.8.3/app/flatpak-complete.h --- flatpak-0.11.7/app/flatpak-complete.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-complete.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,62 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_COMPLETE_H__ +#define __FLATPAK_COMPLETE_H__ + +#include +#include "flatpak-dir-private.h" + +struct FlatpakCompletion { + char *shell_cur; + char *cur; + char *prev; + char *line; + int point; + char **argv; + char **original_argv; + int argc; + int original_argc; +}; + +void flatpak_completion_debug (const gchar *format, ...); + +FlatpakCompletion *flatpak_completion_new (const char *arg_line, + const char *arg_point, + const char *arg_cur); +void flatpak_complete_word (FlatpakCompletion *completion, + char *format, + ...) G_GNUC_PRINTF(2,3); +void flatpak_complete_ref (FlatpakCompletion *completion, + OstreeRepo *repo); +void flatpak_complete_partial_ref (FlatpakCompletion *completion, + FlatpakKinds kinds, + const char *only_arch, + FlatpakDir *dir, + const char *remote); +void flatpak_complete_file (FlatpakCompletion *completion, + const char *file_type); +void flatpak_complete_dir (FlatpakCompletion *completion); +void flatpak_complete_options (FlatpakCompletion *completion, + GOptionEntry *entries); +void flatpak_completion_free (FlatpakCompletion *completion); +void flatpak_complete_context (FlatpakCompletion *completion); + +#endif /* __FLATPAK_COMPLETE_H__ */ diff -Nru flatpak-0.11.7/app/flatpak-main.c flatpak-0.11.8.3/app/flatpak-main.c --- flatpak-0.11.7/app/flatpak-main.c 2018-04-04 16:09:51.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-main.c 2018-06-11 14:52:37.000000000 +0100 @@ -31,7 +31,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" -#include "flatpak-utils.h" +#include "flatpak-utils-private.h" static int opt_verbose; static gboolean opt_ostree_verbose; @@ -68,6 +68,7 @@ { "list", N_("List installed apps and/or runtimes"), flatpak_builtin_list, flatpak_complete_list }, { "info", N_("Show info for installed app or runtime"), flatpak_builtin_info, flatpak_complete_info }, { "config", N_("Configure flatpak"), flatpak_builtin_config, flatpak_complete_config }, + { "repair", N_("Repair flatpak installation"), flatpak_builtin_repair, flatpak_complete_repair }, /* translators: please keep the leading newline and space */ { N_("\n Finding applications and runtimes") }, @@ -583,7 +584,7 @@ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, message_handler, NULL); + g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING, message_handler, NULL); g_set_prgname (argv[0]); diff -Nru flatpak-0.11.7/app/flatpak-table-printer.c flatpak-0.11.8.3/app/flatpak-table-printer.c --- flatpak-0.11.7/app/flatpak-table-printer.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-table-printer.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,258 @@ +/* + * Copyright © 2014 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-table-printer.h" +#include "flatpak-utils-private.h" + +#include +#include +#include +#include + + +typedef struct { + char *text; + int align; +} Cell; + +static void +free_cell (gpointer data) +{ + Cell *cell = data; + + g_free (cell->text); + g_free (cell); +} + +struct FlatpakTablePrinter +{ + GPtrArray *titles; + GPtrArray *rows; + GPtrArray *current; + int n_columns; +}; + +FlatpakTablePrinter * +flatpak_table_printer_new (void) +{ + FlatpakTablePrinter *printer = g_new0 (FlatpakTablePrinter, 1); + + printer->titles = g_ptr_array_new_with_free_func (g_free); + printer->rows = g_ptr_array_new_with_free_func ((GDestroyNotify) g_ptr_array_unref); + printer->current = g_ptr_array_new_with_free_func (free_cell); + + return printer; +} + +void +flatpak_table_printer_free (FlatpakTablePrinter *printer) +{ + g_ptr_array_free (printer->titles, TRUE); + g_ptr_array_free (printer->rows, TRUE); + g_ptr_array_free (printer->current, TRUE); + g_free (printer); +} + +void +flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer, + int column, + const char *text) +{ + g_ptr_array_insert (printer->titles, column, g_strdup (text)); +} + +void +flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer, + const char *text, + int align) +{ + Cell *cell = g_new (Cell, 1); + cell->text = text ? g_strdup (text) : g_strdup (""); + cell->align = align; + g_ptr_array_add (printer->current, cell); +} + +static const char * +find_decimal_point (const char *text) +{ + struct lconv *locale_data; + + locale_data = localeconv (); + return strstr (text, locale_data->decimal_point); +} + +void +flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer, + const char *text) +{ + const char *decimal; + int align = -1; + + decimal = find_decimal_point (text); + if (decimal) + align = decimal - text; + + flatpak_table_printer_add_aligned_column (printer, text, align); +} + +void +flatpak_table_printer_add_column (FlatpakTablePrinter *printer, + const char *text) +{ + flatpak_table_printer_add_aligned_column (printer, text, -1); +} + +void +flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer, + const char *text, + gsize len) +{ + Cell *cell = g_new (Cell, 1); + cell->text = text ? g_strndup (text, len) : g_strdup (""); + cell->align = -1; + g_ptr_array_add (printer->current, cell); +} + +void +flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer, + const char *text) +{ + Cell *cell; + char *new; + + g_assert (printer->current->len > 0); + + cell = g_ptr_array_index (printer->current, printer->current->len - 1); + + if (cell->text[0] != 0) + new = g_strconcat (cell->text, ",", text, NULL); + else + new = g_strdup (text); + + g_free (cell->text); + cell->text = new; +} + +void +flatpak_table_printer_append_with_comma_printf (FlatpakTablePrinter *printer, + const char *format, + ...) +{ + va_list var_args; + g_autofree char *s = NULL; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + va_start (var_args, format); + s = g_strdup_vprintf (format, var_args); + va_end (var_args); +#pragma GCC diagnostic pop + + flatpak_table_printer_append_with_comma (printer, s); +} + +void +flatpak_table_printer_finish_row (FlatpakTablePrinter *printer) +{ + if (printer->current->len == 0) + return; /* Ignore empty rows */ + + printer->n_columns = MAX (printer->n_columns, printer->current->len); + g_ptr_array_add (printer->rows, printer->current); + printer->current = g_ptr_array_new_with_free_func (free_cell); +} + +void +flatpak_table_printer_print (FlatpakTablePrinter *printer) +{ + g_autofree int *widths = NULL; + g_autofree int *lwidths = NULL; + g_autofree int *rwidths = NULL; + int i, j; + + if (printer->current->len != 0) + flatpak_table_printer_finish_row (printer); + + widths = g_new0 (int, printer->n_columns); + lwidths = g_new0 (int, printer->n_columns); + rwidths = g_new0 (int, printer->n_columns); + + for (i = 0; i < printer->titles->len && i < printer->n_columns; i++) + { + char *title = g_ptr_array_index (printer->titles, i); + + if (title) + widths[i] = MAX (widths[i], strlen (title)); + } + + for (i = 0; i < printer->rows->len; i++) + { + GPtrArray *row = g_ptr_array_index (printer->rows, i); + + for (j = 0; j < row->len; j++) + { + Cell *cell = g_ptr_array_index (row, j); + int width; + + width = strlen (cell->text); + widths[j] = MAX (widths[j], width); + if (cell->align >= 0) + { + lwidths[j] = MAX (lwidths[j], cell->align); + rwidths[j] = MAX (rwidths[j], width - cell->align); + } + } + } + + if (flatpak_fancy_output () && printer->titles->len > 0) + { + g_print (FLATPAK_ANSI_BOLD_ON); + for (i = 0; i < printer->titles->len && i < printer->n_columns; i++) + { + char *title = g_ptr_array_index (printer->titles, i); + + g_print ("%s%-*s", (i == 0) ? "" : " ", widths[i], title); + } + g_print (FLATPAK_ANSI_BOLD_OFF); + g_print ("\n"); + } + + for (i = 0; i < printer->rows->len; i++) + { + GPtrArray *row = g_ptr_array_index (printer->rows, i); + + for (j = 0; j < row->len; j++) + { + Cell *cell = g_ptr_array_index (row, j); + if (flatpak_fancy_output ()) + { + if (cell->align < 0) + g_print ("%s%-*s", (j == 0) ? "" : " ", widths[j], cell->text); + else + g_print ("%s%*s%-*s", (j == 0) ? "" : " ", lwidths[j] - cell->align, "", widths[j] - (lwidths[j] - cell->align), cell->text); + } + else + g_print ("%s%s", cell->text, (j < row->len - 1) ? "\t" : ""); + } + g_print ("\n"); + } +} diff -Nru flatpak-0.11.7/app/flatpak-table-printer.h flatpak-0.11.8.3/app/flatpak-table-printer.h --- flatpak-0.11.7/app/flatpak-table-printer.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-table-printer.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright © 2014 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_TABLE_PRINTER_H__ +#define __FLATPAK_TABLE_PRINTER_H__ + +#include + +typedef struct FlatpakTablePrinter FlatpakTablePrinter; + +FlatpakTablePrinter *flatpak_table_printer_new (void); +void flatpak_table_printer_free (FlatpakTablePrinter *printer); +void flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer, + int column, + const char *title); +void flatpak_table_printer_add_column (FlatpakTablePrinter *printer, + const char *text); +void flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer, + const char *text, + int align); +void flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer, + const char *text); +void flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer, + const char *text, + gsize len); +void flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer, + const char *text); +void flatpak_table_printer_append_with_comma_printf (FlatpakTablePrinter *printer, + const char *format, + ...); +void flatpak_table_printer_finish_row (FlatpakTablePrinter *printer); +void flatpak_table_printer_print (FlatpakTablePrinter *printer); + +#endif /* __FLATPAK_TABLE_PRINTER_H__ */ diff -Nru flatpak-0.11.7/app/flatpak-transaction.c flatpak-0.11.8.3/app/flatpak-transaction.c --- flatpak-0.11.7/app/flatpak-transaction.c 2018-04-26 08:41:27.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-transaction.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,941 +0,0 @@ -/* - * Copyright © 2016 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 . - * - * Authors: - * Alexander Larsson - */ - -#include "config.h" - -#include -#include - -#include "flatpak-transaction.h" -#include "flatpak-utils.h" -#include "flatpak-builtins-utils.h" -#include "flatpak-error.h" - -typedef struct FlatpakTransactionOp FlatpakTransactionOp; - -typedef enum { - FLATPAK_TRANSACTION_OP_KIND_INSTALL, - FLATPAK_TRANSACTION_OP_KIND_UPDATE, - FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE, - FLATPAK_TRANSACTION_OP_KIND_BUNDLE -} FlatpakTransactionOpKind; - -struct FlatpakTransactionOp { - char *remote; - char *ref; - /* NULL means unspecified (normally keep whatever was there before), [] means force everything */ - char **subpaths; - char *commit; - GFile *bundle; - FlatpakTransactionOpKind kind; - gboolean non_fatal; - FlatpakTransactionOp *source_op; /* This is the main app/runtime ref for related extensions, and the runtime for apps */ - gboolean failed; - gboolean skipped; -}; - -struct FlatpakTransaction { - FlatpakDir *dir; - GHashTable *refs; - GHashTable *remote_states; /* (element-type utf8 FlatpakRemoteState) */ - GPtrArray *system_dirs; - GList *ops; - GPtrArray *added_origin_remotes; - - gboolean no_interaction; - gboolean no_pull; - gboolean no_deploy; - gboolean no_static_deltas; - gboolean add_deps; - gboolean add_related; - gboolean reinstall; -}; - -static gboolean -remote_name_is_file (const char *remote_name) -{ - return remote_name != NULL && - g_str_has_prefix (remote_name, "file://"); -} - -/* Check if the ref is in the dir, or in the system dir, in case its a - * user-dir or another system-wide installation. We want to avoid depending - * on user-installed things when installing to the system dir. - */ -static gboolean -ref_is_installed (FlatpakTransaction *self, - const char *ref, - GError **error) -{ - g_autoptr(GFile) deploy_dir = NULL; - FlatpakDir *dir = self->dir; - int i; - - deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, NULL); - if (deploy_dir != NULL) - return TRUE; - - /* Don't try to fallback for the system's default directory. */ - if (!flatpak_dir_is_user (dir) && flatpak_dir_get_id (dir) == NULL) - return FALSE; - - /* Lazy initialization of this, once per transaction */ - if (self->system_dirs == NULL) - { - self->system_dirs = flatpak_dir_get_system_list (NULL, error); - if (self->system_dirs == NULL) - return FALSE; - } - - for (i = 0; i < self->system_dirs->len; i++) - { - FlatpakDir *system_dir = g_ptr_array_index (self->system_dirs, i); - - if (g_strcmp0 (flatpak_dir_get_id (dir), flatpak_dir_get_id (system_dir)) == 0) - continue; - - deploy_dir = flatpak_dir_get_if_deployed (system_dir, ref, NULL, NULL); - if (deploy_dir != NULL) - return TRUE; - } - - return FALSE; -} - -static gboolean -dir_ref_is_installed (FlatpakDir *dir, const char *ref, char **remote_out, GVariant **deploy_data_out) -{ - g_autoptr(GVariant) deploy_data = NULL; - - deploy_data = flatpak_dir_get_deploy_data (dir, ref, NULL, NULL); - if (deploy_data == NULL) - return FALSE; - - if (remote_out) - *remote_out = g_strdup (flatpak_deploy_data_get_origin (deploy_data)); - - if (deploy_data_out) - *deploy_data_out = g_variant_ref (deploy_data); - - return TRUE; -} - -static FlatpakTransactionOp * -flatpak_transaction_operation_new (const char *remote, - const char *ref, - const char **subpaths, - const char *commit, - GFile *bundle, - FlatpakTransactionOpKind kind) -{ - FlatpakTransactionOp *self = g_new0 (FlatpakTransactionOp, 1); - - self->remote = g_strdup (remote); - self->ref = g_strdup (ref); - self->subpaths = g_strdupv ((char **)subpaths); - self->commit = g_strdup (commit); - if (bundle) - self->bundle = g_object_ref (bundle); - self->kind = kind; - - return self; -} - -static void -flatpak_transaction_operation_free (FlatpakTransactionOp *self) -{ - g_free (self->remote); - g_free (self->ref); - g_free (self->commit); - g_strfreev (self->subpaths); - g_clear_object (&self->bundle); - g_free (self); -} - -gboolean -flatpak_transaction_is_empty (FlatpakTransaction *self) -{ - return self->ops == NULL; -} - -FlatpakTransaction * -flatpak_transaction_new (FlatpakDir *dir, - gboolean no_interaction, - gboolean no_pull, - gboolean no_deploy, - gboolean no_static_deltas, - gboolean add_deps, - gboolean add_related, - gboolean reinstall) -{ - FlatpakTransaction *t = g_new0 (FlatpakTransaction, 1); - - t->dir = g_object_ref (dir); - t->refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - t->remote_states = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)flatpak_remote_state_free); - t->added_origin_remotes = g_ptr_array_new_with_free_func (g_free); - - t->no_interaction = no_interaction; - t->no_pull = no_pull; - t->no_deploy = no_deploy; - t->no_static_deltas = no_static_deltas; - t->add_deps = add_deps; - t->add_related = add_related; - t->reinstall = reinstall; - return t; -} - -void -flatpak_transaction_free (FlatpakTransaction *self) -{ - g_hash_table_unref (self->refs); - g_hash_table_unref (self->remote_states); - g_list_free_full (self->ops, (GDestroyNotify)flatpak_transaction_operation_free); - g_object_unref (self->dir); - - g_ptr_array_unref (self->added_origin_remotes); - - if (self->system_dirs != NULL) - g_ptr_array_free (self->system_dirs, TRUE); - - g_free (self); -} - -static FlatpakTransactionOp * -flatpak_transaction_get_op_for_ref (FlatpakTransaction *self, - const char *ref) -{ - FlatpakTransactionOp *op; - - op = g_hash_table_lookup (self->refs, ref); - - return op; -} - -static char * -subpaths_to_string (const char **subpaths) -{ - GString *s = NULL; - int i; - - if (subpaths == NULL) - return g_strdup ("[$old]"); - - if (*subpaths == 0) - return g_strdup ("[*]"); - - s = g_string_new ("["); - for (i = 0; subpaths[i] != NULL; i++) - { - if (i != 0) - g_string_append (s, ", "); - g_string_append (s, subpaths[i]); - } - g_string_append (s, "]"); - - return g_string_free (s, FALSE); -} - -static const char * -kind_to_str (FlatpakTransactionOpKind kind) -{ - switch (kind) - { - case FLATPAK_TRANSACTION_OP_KIND_INSTALL: - return "install"; - case FLATPAK_TRANSACTION_OP_KIND_UPDATE: - return "update"; - case FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE: - return "install/update"; - case FLATPAK_TRANSACTION_OP_KIND_BUNDLE: - return "install bundle"; - } - return "unknown"; -} - -static FlatpakRemoteState * -flatpak_transaction_ensure_remote_state (FlatpakTransaction *self, - const char *remote, - GError **error) -{ - FlatpakRemoteState *state; - - state = g_hash_table_lookup (self->remote_states, remote); - if (state) - return state; - - state = flatpak_dir_get_remote_state_optional (self->dir, remote, NULL, error); - - if (state) - g_hash_table_insert (self->remote_states, state->remote_name, state); - - return state; -} - -static FlatpakTransactionOp * -flatpak_transaction_add_op (FlatpakTransaction *self, - const char *remote, - const char *ref, - const char **subpaths, - const char *commit, - GFile *bundle, - FlatpakTransactionOpKind kind) -{ - FlatpakTransactionOp *op; - g_autofree char *subpaths_str = NULL; - - subpaths_str = subpaths_to_string (subpaths); - g_debug ("Transaction: %s %s:%s%s%s%s", - kind_to_str (kind), remote, ref, - commit != NULL ? "@" : "", - commit != NULL ? commit : "", - subpaths_str); - - op = g_hash_table_lookup (self->refs, ref); - if (op != NULL) - { - g_auto(GStrv) old_subpaths = op->subpaths; - op->subpaths = flatpak_subpaths_merge (old_subpaths, (char **)subpaths); - - return op; - } - - op = flatpak_transaction_operation_new (remote, ref, subpaths, commit, bundle, kind); - g_hash_table_insert (self->refs, g_strdup (ref), op); - self->ops = g_list_prepend (self->ops, op); - - return op; -} - -static char * -ask_for_remote (FlatpakTransaction *self, const char **remotes) -{ - int n_remotes = g_strv_length ((char **)remotes); - int chosen = 0; - int i; - - if (self->no_interaction) - { - chosen = 1; - g_print (_("Found in remote %s\n"), remotes[0]); - } - else if (n_remotes == 1) - { - if (flatpak_yes_no_prompt (_("Found in remote %s, do you want to install it?"), remotes[0])) - chosen = 1; - } - else - { - g_print (_("Found in several remotes:\n")); - for (i = 0; remotes[i] != NULL; i++) - { - g_print ("%d) %s\n", i + 1, remotes[i]); - } - chosen = flatpak_number_prompt (0, n_remotes, _("Which do you want to install (0 to abort)?")); - } - - if (chosen == 0) - return NULL; - - return g_strdup (remotes[chosen-1]); -} - -static gboolean -add_related (FlatpakTransaction *self, - FlatpakRemoteState *state, - const char *remote, - const char *ref, - FlatpakTransactionOp *source_op, - GError **error) -{ - g_autoptr(GPtrArray) related = NULL; - g_autoptr(GError) local_error = NULL; - int i; - - if (!self->add_related) - return TRUE; - - if (self->no_pull) - related = flatpak_dir_find_local_related (self->dir, ref, remote, NULL, &local_error); - else - related = flatpak_dir_find_remote_related (self->dir, state, ref, NULL, &local_error); - if (related == NULL) - { - g_printerr (_("Warning: Problem looking for related refs: %s\n"), local_error->message); - g_clear_error (&local_error); - } - else - { - for (i = 0; i < related->len; i++) - { - FlatpakRelated *rel = g_ptr_array_index (related, i); - FlatpakTransactionOp *op; - - if (!rel->download) - continue; - - op = flatpak_transaction_add_op (self, remote, rel->ref, - (const char **)rel->subpaths, - NULL, NULL, - FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE); - op->non_fatal = TRUE; - op->source_op = source_op; - } - } - - return TRUE; -} - -static gboolean -add_deps (FlatpakTransaction *self, - GKeyFile *metakey, - FlatpakRemoteState *state, - const char *remote, - const char *ref, - FlatpakTransactionOp **dep_op, - GError **error) -{ - g_autofree char *runtime_ref = NULL; - g_autofree char *full_runtime_ref = NULL; - g_autofree char *runtime_remote = NULL; - FlatpakTransactionOp *op = NULL; - const char *pref; - - if (!g_str_has_prefix (ref, "app/")) - return TRUE; - - if (metakey) - runtime_ref = g_key_file_get_string (metakey, "Application", "runtime", NULL); - if (runtime_ref == NULL) - return TRUE; - - pref = strchr (ref, '/') + 1; - - full_runtime_ref = g_strconcat ("runtime/", runtime_ref, NULL); - - op = flatpak_transaction_get_op_for_ref (self, full_runtime_ref); - if (op == NULL) - { - g_autoptr(GError) local_error = NULL; - - if (!ref_is_installed (self, full_runtime_ref, &local_error)) - { - g_auto(GStrv) remotes = NULL; - - if (local_error != NULL) - { - g_propagate_error (error, g_steal_pointer (&local_error)); - return FALSE; - } - - g_print (_("Required runtime for %s (%s) is not installed, searching...\n"), - pref, runtime_ref); - - remotes = flatpak_dir_search_for_dependency (self->dir, full_runtime_ref, NULL, NULL); - if (remotes == NULL || *remotes == NULL) - { - g_print (_("The required runtime %s was not found in a configured remote.\n"), - runtime_ref); - } - else - { - runtime_remote = ask_for_remote (self, (const char **)remotes); - } - - if (runtime_remote == NULL) - return flatpak_fail (error, - "The Application %s requires the runtime %s which is not installed", - pref, runtime_ref); - - op = flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL, - FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE); - } - else - { - /* Update if in same dir */ - if (dir_ref_is_installed (self->dir, full_runtime_ref, &runtime_remote, NULL)) - { - g_debug ("Updating dependent runtime %s", full_runtime_ref); - op = flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL, - FLATPAK_TRANSACTION_OP_KIND_UPDATE); - op->non_fatal = TRUE; - } - } - } - - if (runtime_remote != NULL && - !add_related (self, state, runtime_remote, full_runtime_ref, op, error)) - return FALSE; - - if (dep_op) - *dep_op = op; - - return TRUE; -} - -static gboolean -flatpak_transaction_add_ref (FlatpakTransaction *self, - const char *remote, - const char *ref, - const char **subpaths, - const char *commit, - FlatpakTransactionOpKind kind, - GFile *bundle, - const char *metadata, - GError **error) -{ - g_autofree char *origin = NULL; - const char *pref; - g_autoptr(GKeyFile) metakey = NULL; - g_autoptr(GError) local_error = NULL; - g_autofree char *origin_remote = NULL; - FlatpakRemoteState *state; - FlatpakTransactionOp *dep_op = NULL; - FlatpakTransactionOp *main_op; - - if (remote_name_is_file (remote)) - { - g_auto(GStrv) parts = NULL; - parts = g_strsplit (ref, "/", -1); - - origin_remote = flatpak_dir_create_origin_remote (self->dir, - remote, /* uri */ - parts[1], - "Local repo", - ref, - NULL, - NULL, - NULL, error); - if (origin_remote == NULL) - return FALSE; - - g_ptr_array_add (self->added_origin_remotes, g_strdup (origin_remote)); - - remote = origin_remote; - } - - pref = strchr (ref, '/') + 1; - - if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE) - { - if (!dir_ref_is_installed (self->dir, ref, &origin, NULL)) - { - g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, - _("%s not installed"), pref); - return FALSE; - } - - if (flatpak_dir_get_remote_disabled (self->dir, origin)) - { - g_debug (_("Remote %s disabled, ignoring %s update"), origin, pref); - return TRUE; - } - remote = origin; - } - else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL) - { - g_assert (remote != NULL); - if (!self->reinstall && - dir_ref_is_installed (self->dir, ref, &origin, NULL)) - { - if (strcmp (remote, origin) == 0) - { - g_printerr (_("%s already installed, skipping\n"), pref); - return TRUE; - } - else - { - g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED, - _("%s is already installed from other remote (%s)"), pref, origin); - return FALSE; - } - } - } - - state = flatpak_transaction_ensure_remote_state (self, remote, error); - if (state == NULL) - return FALSE; - - if (metadata == NULL && remote != NULL) - { - if (!flatpak_remote_state_lookup_cache (state, ref, NULL, NULL, &metadata, &local_error)) - { - g_print (_("Warning: Can't find dependencies: %s\n"), local_error->message); - g_clear_error (&local_error); - } - } - - if (metadata) - { - metakey = g_key_file_new (); - if (!g_key_file_load_from_data (metakey, metadata, -1, 0, NULL)) - g_clear_object (&metakey); - } - - if (metakey) - { - g_autofree char *required_version = NULL; - const char *group; - int required_major, required_minor, required_micro; - - if (g_str_has_prefix (ref, "app/")) - group = "Application"; - else - group = "Runtime"; - - required_version = g_key_file_get_string (metakey, group, "required-flatpak", NULL); - if (required_version) - { - if (sscanf (required_version, "%d.%d.%d", &required_major, &required_minor, &required_micro) != 3) - g_print (_("Invalid require-flatpak argument %s\n"), required_version); - else - { - if (required_major > PACKAGE_MAJOR_VERSION || - (required_major == PACKAGE_MAJOR_VERSION && required_minor > PACKAGE_MINOR_VERSION) || - (required_major == PACKAGE_MAJOR_VERSION && required_minor == PACKAGE_MINOR_VERSION && required_micro > PACKAGE_MICRO_VERSION)) - return flatpak_fail (error, _("%s needs a later flatpak version (%s)"), ref, required_version); - } - } - } - - if (self->add_deps) - { - if (!add_deps (self, metakey, state, remote, ref, &dep_op, error)) - return FALSE; - } - - main_op = flatpak_transaction_add_op (self, remote, ref, subpaths, commit, bundle, kind); - main_op->source_op = dep_op; - - if (!add_related (self, state, remote, ref, main_op, error)) - return FALSE; - - return TRUE; -} - -gboolean -flatpak_transaction_add_install (FlatpakTransaction *self, - const char *remote, - const char *ref, - const char **subpaths, - GError **error) -{ - const char *all_paths[] = { NULL }; - - /* If we install with no special args pull all subpaths */ - if (subpaths == NULL) - subpaths = all_paths; - - return flatpak_transaction_add_ref (self, remote, ref, subpaths, NULL, FLATPAK_TRANSACTION_OP_KIND_INSTALL, NULL, NULL, error); -} - -gboolean -flatpak_transaction_add_install_bundle (FlatpakTransaction *self, - GFile *file, - GBytes *gpg_data, - GError **error) -{ - g_autofree char *remote = NULL; - g_autofree char *ref = NULL; - g_autofree char *metadata = NULL; - gboolean created_remote; - - remote = flatpak_dir_ensure_bundle_remote (self->dir, file, gpg_data, - &ref, &metadata, &created_remote, - NULL, error); - if (remote == NULL) - return FALSE; - - if (!flatpak_dir_recreate_repo (self->dir, NULL, error)) - return FALSE; - - return flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, FLATPAK_TRANSACTION_OP_KIND_BUNDLE, file, metadata, error); -} - -gboolean -flatpak_transaction_add_update (FlatpakTransaction *self, - const char *ref, - const char **subpaths, - const char *commit, - GError **error) -{ - const char *all_paths[] = { NULL }; - - /* If specify an empty subpath, that means all subpaths */ - if (subpaths != NULL && subpaths[0] != NULL && subpaths[0][0] == 0) - subpaths = all_paths; - - return flatpak_transaction_add_ref (self, NULL, ref, subpaths, commit, FLATPAK_TRANSACTION_OP_KIND_UPDATE, NULL, NULL, error); -} - -gboolean -flatpak_transaction_update_metadata (FlatpakTransaction *self, - gboolean all_remotes, - GCancellable *cancellable, - GError **error) -{ - g_auto(GStrv) remotes = NULL; - int i; - GList *l; - - /* Collect all dir+remotes used in this transaction */ - - if (all_remotes) - { - remotes = flatpak_dir_list_remotes (self->dir, NULL, error); - if (remotes == NULL) - return FALSE; - } - else - { - g_autoptr(GHashTable) ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - for (l = self->ops; l != NULL; l = l->next) - { - FlatpakTransactionOp *op = l->data; - g_hash_table_add (ht, g_strdup (op->remote)); - } - remotes = (char **)g_hash_table_get_keys_as_array (ht, NULL); - g_hash_table_steal_all (ht); /* Move ownership to remotes */ - } - - /* Update metadata for said remotes */ - for (i = 0; remotes[i] != NULL; i++) - { - char *remote = remotes[i]; - g_autoptr(GError) my_error = NULL; - - g_debug ("Updating remote metadata for %s", remote); - if (!flatpak_dir_update_remote_configuration (self->dir, remote, cancellable, &my_error)) - g_printerr (_("Error updating remote metadata for '%s': %s\n"), remote, my_error->message); - } - - /* Reload changed configuration */ - if (!flatpak_dir_recreate_repo (self->dir, cancellable, error)) - return FALSE; - - return TRUE; -} - -gboolean -flatpak_transaction_run (FlatpakTransaction *self, - gboolean stop_on_first_error, - GCancellable *cancellable, - GError **error) -{ - GList *l; - gboolean succeeded = TRUE; - int i; - - self->ops = g_list_reverse (self->ops); - - for (l = self->ops; l != NULL; l = l->next) - { - FlatpakTransactionOp *op = l->data; - g_autoptr(GError) local_error = NULL; - gboolean res = TRUE; - gboolean skipped = FALSE; - const char *pref; - const char *opname; - FlatpakTransactionOpKind kind; - FlatpakTerminalProgress terminal_progress = { 0 }; - FlatpakRemoteState *state; - - kind = op->kind; - if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE) - { - g_autoptr(GVariant) deploy_data = NULL; - - if (dir_ref_is_installed (self->dir, op->ref, NULL, &deploy_data)) - { - /* Don't use the remote from related ref on update, always use - the current remote. */ - g_free (op->remote); - op->remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data)); - - kind = FLATPAK_TRANSACTION_OP_KIND_UPDATE; - } - else - kind = FLATPAK_TRANSACTION_OP_KIND_INSTALL; - - op->kind = kind; - } - - pref = strchr (op->ref, '/') + 1; - - if (op->source_op && (op->source_op->failed || op->source_op->skipped) && - /* Allow installing an app if the runtime failed to update (i.e. is installed) because - * the app should still run, and otherwise you could never install the app until the runtime - * remote is fixed. */ - !(op->source_op->kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE && g_str_has_prefix (op->ref, "app/"))) - { - g_printerr (_("Skipping %s due to previous error\n"), pref); - skipped = TRUE; - } - else if ((state = flatpak_transaction_ensure_remote_state (self, op->remote, &local_error)) == NULL) - { - opname = _("fetch remote info"); - res = FALSE; - } - else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL) - { - g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress); - opname = _("install"); - if (flatpak_dir_is_user (self->dir)) - g_print (_("Installing for user: %s from %s\n"), pref, op->remote); - else - g_print (_("Installing: %s from %s\n"), pref, op->remote); - res = flatpak_dir_install (self->dir , - self->no_pull, - self->no_deploy, - self->no_static_deltas, - self->reinstall, - state, op->ref, - (const char **)op->subpaths, - progress, - cancellable, &local_error); - ostree_async_progress_finish (progress); - flatpak_terminal_progress_end (&terminal_progress); - } - else if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE) - { - g_auto(OstreeRepoFinderResultv) check_results = NULL; - - opname = _("update"); - g_autofree char *target_commit = flatpak_dir_check_for_update (self->dir, state, op->ref, op->commit, - (const char **)op->subpaths, - self->no_pull, - &check_results, - cancellable, &local_error); - if (target_commit != NULL) - { - if (flatpak_dir_is_user (self->dir)) - g_print (_("Updating for user: %s from %s\n"), pref, op->remote); - else - g_print (_("Updating: %s from %s\n"), pref, op->remote); - g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress); - res = flatpak_dir_update (self->dir, - self->no_pull, - self->no_deploy, - self->no_static_deltas, - op->commit != NULL, /* Allow downgrade if we specify commit */ - state, op->ref, target_commit, - (const OstreeRepoFinderResult * const *) check_results, - (const char **)op->subpaths, - progress, - cancellable, &local_error); - ostree_async_progress_finish (progress); - flatpak_terminal_progress_end (&terminal_progress); - if (res) - { - g_autoptr(GVariant) deploy_data = NULL; - g_autofree char *commit = NULL; - deploy_data = flatpak_dir_get_deploy_data (self->dir, op->ref, NULL, NULL); - commit = g_strndup (flatpak_deploy_data_get_commit (deploy_data), 12); - g_print (_("Now at %s.\n"), commit); - } - - /* Handle noop-updates */ - if (!res && g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) - { - g_print (_("No updates.\n")); - res = TRUE; - g_clear_error (&local_error); - } - } - else - { - res = FALSE; - if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) - { - res = TRUE; - g_clear_error (&local_error); - } - } - } - else if (kind == FLATPAK_TRANSACTION_OP_KIND_BUNDLE) - { - g_autofree char *bundle_basename = g_file_get_basename (op->bundle); - opname = _("install bundle"); - if (flatpak_dir_is_user (self->dir)) - g_print (_("Installing for user: %s from bundle %s\n"), pref, bundle_basename); - else - g_print (_("Installing: %s from bundle %s\n"), pref, bundle_basename); - res = flatpak_dir_install_bundle (self->dir, op->bundle, - op->remote, NULL, - cancellable, &local_error); - } - else - g_assert_not_reached (); - - if (res && !skipped) - { - g_autoptr(GVariant) deploy_data = NULL; - deploy_data = flatpak_dir_get_deploy_data (self->dir, op->ref, NULL, NULL); - - const char *eol = flatpak_deploy_data_get_eol (deploy_data); - const char *eol_rebase = flatpak_deploy_data_get_eol_rebase (deploy_data); - - if (eol_rebase) - { - g_printerr ("Warning: %s is end-of-line, in preference of %s\n", op->ref, eol_rebase); - } - else if (eol) - { - g_printerr ("Warning: %s is end-of-line, with reason: %s\n", op->ref, eol); - } - } - - op->skipped = skipped; - if (!res) - { - op->failed = TRUE; - if (op->non_fatal) - { - g_printerr (_("Warning: Failed to %s %s: %s\n"), - opname, pref, local_error->message); - } - else if (!stop_on_first_error) - { - g_printerr (_("Error: Failed to %s %s: %s\n"), - opname, pref, local_error->message); - if (succeeded) - { - succeeded = FALSE; - flatpak_fail (error, _("One or more operations failed")); - } - } - else - { - succeeded = FALSE; - g_propagate_error (error, g_steal_pointer (&local_error)); - goto out; - } - } - } - - out: - - flatpak_dir_prune (self->dir, cancellable, NULL); - - for (i = 0; i < self->added_origin_remotes->len; i++) - flatpak_dir_prune_origin_remote (self->dir, g_ptr_array_index (self->added_origin_remotes, i)); - - return succeeded; -} diff -Nru flatpak-0.11.7/app/flatpak-transaction.h flatpak-0.11.8.3/app/flatpak-transaction.h --- flatpak-0.11.7/app/flatpak-transaction.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/app/flatpak-transaction.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,67 +0,0 @@ -/* - * Copyright © 2016 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_TRANSACTION_H__ -#define __FLATPAK_TRANSACTION_H__ - -#include -#include "libglnx/libglnx.h" - -#include "flatpak-dir.h" - -typedef struct FlatpakTransaction FlatpakTransaction; - -FlatpakTransaction *flatpak_transaction_new (FlatpakDir *dir, - gboolean no_interaction, - gboolean no_pull, - gboolean no_deploy, - gboolean no_static_deltas, - gboolean add_deps, - gboolean add_related, - gboolean reinstall); -void flatpak_transaction_free (FlatpakTransaction *self); -gboolean flatpak_transaction_update_metadata (FlatpakTransaction *self, - gboolean all_remotes, - GCancellable *cancellable, - GError **error); -gboolean flatpak_transaction_run (FlatpakTransaction *self, - gboolean stop_on_first_errror, - GCancellable *cancellable, - GError **error); -gboolean flatpak_transaction_add_install (FlatpakTransaction *self, - const char *remote, - const char *ref, - const char **subpaths, - GError **error); -gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction *self, - GFile *file, - GBytes *gpg_data, - GError **error); -gboolean flatpak_transaction_add_update (FlatpakTransaction *self, - const char *ref, - const char **subpaths, - const char *commit, - GError **error); -gboolean flatpak_transaction_is_empty (FlatpakTransaction *self); - - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTransaction, flatpak_transaction_free) - -#endif /* __FLATPAK_TRANSACTION_H__ */ diff -Nru flatpak-0.11.7/app/Makefile.am.inc flatpak-0.11.8.3/app/Makefile.am.inc --- flatpak-0.11.7/app/Makefile.am.inc 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/app/Makefile.am.inc 2018-06-11 14:52:37.000000000 +0100 @@ -9,8 +9,6 @@ app/flatpak-builtins.h \ app/flatpak-builtins-utils.h \ app/flatpak-builtins-utils.c \ - app/flatpak-transaction.h \ - app/flatpak-transaction.c \ app/flatpak-builtins-add-remote.c \ app/flatpak-builtins-delete-remote.c \ app/flatpak-builtins-list-remotes.c \ @@ -41,6 +39,13 @@ app/flatpak-builtins-document-info.c \ app/flatpak-builtins-document-list.c \ app/flatpak-builtins-search.c \ + app/flatpak-builtins-repair.c \ + app/flatpak-table-printer.c \ + app/flatpak-table-printer.h \ + app/flatpak-complete.c \ + app/flatpak-complete.h \ + app/flatpak-cli-transaction.c \ + app/flatpak-cli-transaction.h \ app/parse-datetime.h \ $(NULL) @@ -56,5 +61,6 @@ flatpak_LDADD = $(AM_LDADD) $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(JSON_LIBS) $(APPSTREAM_GLIB_LIBS) \ libglnx.la libflatpak-common.la flatpak_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) $(APPSTREAM_GLIB_CFLAGS) \ + -DFLATPAK_COMPILATION \ -I$(srcdir)/app \ -DLOCALEDIR=\"$(localedir)\" diff -Nru flatpak-0.11.7/common/flatpak-bundle-ref.c flatpak-0.11.8.3/common/flatpak-bundle-ref.c --- flatpak-0.11.7/common/flatpak-bundle-ref.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-bundle-ref.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,339 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include + +#include "flatpak-utils-private.h" +#include "flatpak-bundle-ref.h" +#include "flatpak-enum-types.h" + +typedef struct _FlatpakBundleRefPrivate FlatpakBundleRefPrivate; + +struct _FlatpakBundleRefPrivate +{ + GFile *file; + char *origin; + char *runtime_repo; + GBytes *metadata; + GBytes *appstream; + GBytes *icon_64; + GBytes *icon_128; + guint64 installed_size; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakBundleRef, flatpak_bundle_ref, FLATPAK_TYPE_REF) + +enum { + PROP_0, + + PROP_FILE, +}; + +static void +flatpak_bundle_ref_finalize (GObject *object) +{ + FlatpakBundleRef *self = FLATPAK_BUNDLE_REF (object); + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + g_clear_object (&priv->file); + + g_bytes_unref (priv->metadata); + g_bytes_unref (priv->appstream); + g_bytes_unref (priv->icon_64); + g_bytes_unref (priv->icon_128); + g_free (priv->origin); + g_free (priv->runtime_repo); + + G_OBJECT_CLASS (flatpak_bundle_ref_parent_class)->finalize (object); +} + +static void +flatpak_bundle_ref_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakBundleRef *self = FLATPAK_BUNDLE_REF (object); + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_FILE: + g_set_object (&priv->file, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_bundle_ref_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakBundleRef *self = FLATPAK_BUNDLE_REF (object); + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_FILE: + g_value_set_object (value, priv->file); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_bundle_ref_class_init (FlatpakBundleRefClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_bundle_ref_get_property; + object_class->set_property = flatpak_bundle_ref_set_property; + object_class->finalize = flatpak_bundle_ref_finalize; + + g_object_class_install_property (object_class, + PROP_FILE, + g_param_spec_object ("file", + "", + "", + G_TYPE_FILE, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); +} + +static void +flatpak_bundle_ref_init (FlatpakBundleRef *self) +{ +} + +/** + * flatpak_bundle_ref_get_file: + * @self: a #FlatpakBundleRef + * + * Get the file this bundle is stored in. + * + * Returns: (transfer full) : an #GFile + */ +GFile * +flatpak_bundle_ref_get_file (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + return g_object_ref (priv->file); +} + +/** + * flatpak_bundle_ref_get_metadata: + * @self: a #FlatpakBundleRef + * + * Get the metadata for the app/runtime + * + * Returns: (transfer full) : an #GBytes with the metadata contents, or %NULL + */ +GBytes * +flatpak_bundle_ref_get_metadata (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + if (priv->metadata) + return g_bytes_ref (priv->metadata); + return NULL; +} + +/** + * flatpak_bundle_ref_get_appstream: + * @self: a #FlatpakBundleRef + * + * Get the compressed appstream for the app/runtime + * + * Returns: (transfer full) : an #GBytes with the appstream contents, or %NULL + */ +GBytes * +flatpak_bundle_ref_get_appstream (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + if (priv->appstream) + return g_bytes_ref (priv->appstream); + return NULL; +} + +/** + * flatpak_bundle_ref_get_icon: + * @self: a #FlatpakBundleRef + * @size: 64 or 128 + * + * Get the icon png data for the app/runtime + * + * Returns: (transfer full) : an #GBytes with png contents + */ +GBytes * +flatpak_bundle_ref_get_icon (FlatpakBundleRef *self, + int size) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + if (size == 64 && priv->icon_64) + return g_bytes_ref (priv->icon_64); + + if (size == 128 && priv->icon_128) + return g_bytes_ref (priv->icon_128); + + return NULL; +} + +/** + * flatpak_bundle_ref_get_origin: + * @self: a #FlatpakBundleRef + * + * Get the origin url stored in the bundle + * + * Returns: (transfer full) : an url string, or %NULL + */ +char * +flatpak_bundle_ref_get_origin (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + return g_strdup (priv->origin); +} + + +/** + * flatpak_bundle_ref_get_runtime_repo: + * @self: a #FlatpakBundleRef + * + * Get the runtime flatpakrepo url stored in the bundle (if any) + * + * Returns: (transfer full) : an url string, or %NULL + * + * Since: 0.8.0 + */ +char * +flatpak_bundle_ref_get_runtime_repo_url (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + return g_strdup (priv->runtime_repo); +} + +/** + * flatpak_bundle_ref_get_installed_size: + * @self: a FlatpakBundleRef + * + * Returns the installed size for the bundle. + * + * Returns: the installed size + */ +guint64 +flatpak_bundle_ref_get_installed_size (FlatpakBundleRef *self) +{ + FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self); + + return priv->installed_size; +} + +/** + * flatpak_bundle_ref_new: + * @file: a #GFile + * @error: (allow-none): return location for an error + * + * Creates a new bundle ref for the given file. + * + * Returns: a new bundle ref. + */ +FlatpakBundleRef * +flatpak_bundle_ref_new (GFile *file, + GError **error) +{ + FlatpakRefKind kind = FLATPAK_REF_KIND_APP; + FlatpakBundleRefPrivate *priv; + + g_auto(GStrv) parts = NULL; + FlatpakBundleRef *ref; + g_autoptr(GVariant) metadata = NULL; + g_autofree char *commit = NULL; + g_autofree char *full_ref = NULL; + g_autofree char *origin = NULL; + g_autofree char *runtime_repo = NULL; + g_autofree char *metadata_contents = NULL; + g_autoptr(GVariant) appstream = NULL; + g_autoptr(GVariant) icon_64 = NULL; + g_autoptr(GVariant) icon_128 = NULL; + guint64 installed_size; + g_autofree char *collection_id = NULL; + + metadata = flatpak_bundle_load (file, &commit, &full_ref, &origin, &runtime_repo, &metadata_contents, &installed_size, + NULL, &collection_id, error); + if (metadata == NULL) + return NULL; + + parts = flatpak_decompose_ref (full_ref, error); + if (parts == NULL) + return NULL; + + if (strcmp (parts[0], "app") != 0) + kind = FLATPAK_REF_KIND_RUNTIME; + + ref = g_object_new (FLATPAK_TYPE_BUNDLE_REF, + "kind", kind, + "name", parts[1], + "arch", parts[2], + "branch", parts[3], + "commit", commit, + "file", file, +#ifdef FLATPAK_ENABLE_P2P + "collection-id", collection_id, +#endif /* FLATPAK_ENABLE_P2P */ + NULL); + priv = flatpak_bundle_ref_get_instance_private (ref); + + if (metadata_contents) + priv->metadata = g_bytes_new_take (metadata_contents, + strlen (metadata_contents)); + metadata_contents = NULL; /* Stolen */ + + appstream = g_variant_lookup_value (metadata, "appdata", G_VARIANT_TYPE_BYTESTRING); + if (appstream) + priv->appstream = g_variant_get_data_as_bytes (appstream); + + icon_64 = g_variant_lookup_value (metadata, "icon-64", G_VARIANT_TYPE_BYTESTRING); + if (icon_64) + priv->icon_64 = g_variant_get_data_as_bytes (icon_64); + + icon_128 = g_variant_lookup_value (metadata, "icon-128", G_VARIANT_TYPE_BYTESTRING); + if (icon_128) + priv->icon_128 = g_variant_get_data_as_bytes (icon_128); + + priv->installed_size = installed_size; + + priv->origin = g_steal_pointer (&origin); + priv->runtime_repo = g_steal_pointer (&runtime_repo); + + return ref; +} diff -Nru flatpak-0.11.7/common/flatpak-bundle-ref.h flatpak-0.11.8.3/common/flatpak-bundle-ref.h --- flatpak-0.11.7/common/flatpak-bundle-ref.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-bundle-ref.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_BUNDLE_REF_H__ +#define __FLATPAK_BUNDLE_REF_H__ + +typedef struct _FlatpakBundleRef FlatpakBundleRef; + +#include +#include + +#define FLATPAK_TYPE_BUNDLE_REF flatpak_bundle_ref_get_type () +#define FLATPAK_BUNDLE_REF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_BUNDLE_REF, FlatpakBundleRef)) +#define FLATPAK_IS_BUNDLE_REF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_BUNDLE_REF)) + +FLATPAK_EXTERN GType flatpak_bundle_ref_get_type (void); + +struct _FlatpakBundleRef +{ + FlatpakRef parent; +}; + +typedef struct +{ + FlatpakRefClass parent_class; +} FlatpakBundleRefClass; + +FLATPAK_EXTERN FlatpakBundleRef *flatpak_bundle_ref_new (GFile *file, + GError **error); +FLATPAK_EXTERN GFile *flatpak_bundle_ref_get_file (FlatpakBundleRef *self); +FLATPAK_EXTERN GBytes *flatpak_bundle_ref_get_metadata (FlatpakBundleRef *self); +FLATPAK_EXTERN GBytes *flatpak_bundle_ref_get_appstream (FlatpakBundleRef *self); +FLATPAK_EXTERN GBytes *flatpak_bundle_ref_get_icon (FlatpakBundleRef *self, + int size); +FLATPAK_EXTERN char *flatpak_bundle_ref_get_origin (FlatpakBundleRef *self); +FLATPAK_EXTERN guint64 flatpak_bundle_ref_get_installed_size (FlatpakBundleRef *self); +FLATPAK_EXTERN char *flatpak_bundle_ref_get_runtime_repo_url (FlatpakBundleRef *self); + + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakBundleRef, g_object_unref) +#endif + +#endif /* __FLATPAK_BUNDLE_REF_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-bwrap.c flatpak-0.11.8.3/common/flatpak-bwrap.c --- flatpak-0.11.7/common/flatpak-bwrap.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-bwrap.c 2018-05-30 13:58:57.000000000 +0100 @@ -37,8 +37,8 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-bwrap.h" -#include "flatpak-utils.h" +#include "flatpak-bwrap-private.h" +#include "flatpak-utils-private.h" static void clear_fd (gpointer data) @@ -48,12 +48,16 @@ close (*fd_p); } +char *flatpak_bwrap_empty_env[] = { NULL }; + FlatpakBwrap * flatpak_bwrap_new (char **env) { FlatpakBwrap *bwrap = g_new0 (FlatpakBwrap, 1); bwrap->argv = g_ptr_array_new_with_free_func (g_free); + bwrap->noinherit_fds = g_array_new (FALSE, TRUE, sizeof (int)); + g_array_set_clear_func (bwrap->noinherit_fds, clear_fd); bwrap->fds = g_array_new (FALSE, TRUE, sizeof (int)); g_array_set_clear_func (bwrap->fds, clear_fd); @@ -69,11 +73,18 @@ flatpak_bwrap_free (FlatpakBwrap *bwrap) { g_ptr_array_unref (bwrap->argv); + g_array_unref (bwrap->noinherit_fds); g_array_unref (bwrap->fds); g_strfreev (bwrap->envp); g_free (bwrap); } +gboolean +flatpak_bwrap_is_empty (FlatpakBwrap *bwrap) +{ + return bwrap->argv->len == 0; +} + void flatpak_bwrap_set_env (FlatpakBwrap *bwrap, const char *variable, @@ -91,6 +102,41 @@ } void +flatpak_bwrap_add_arg (FlatpakBwrap *bwrap, const char *arg) +{ + g_ptr_array_add (bwrap->argv, g_strdup (arg)); +} + +void +flatpak_bwrap_finish (FlatpakBwrap *bwrap) +{ + g_ptr_array_add (bwrap->argv, NULL); +} + +void +flatpak_bwrap_add_noinherit_fd (FlatpakBwrap *bwrap, + int fd) +{ + g_array_append_val (bwrap->noinherit_fds, fd); +} + +void +flatpak_bwrap_add_fd (FlatpakBwrap *bwrap, + int fd) +{ + g_array_append_val (bwrap->fds, fd); +} + +void +flatpak_bwrap_add_arg_printf (FlatpakBwrap *bwrap, const char *format, ...) +{ + va_list args; + + va_start (args, format); + g_ptr_array_add (bwrap->argv, g_strdup_vprintf (format, args)); + va_end (args); +} +void flatpak_bwrap_add_args (FlatpakBwrap *bwrap, ...) { va_list args; @@ -98,7 +144,7 @@ va_start (args, bwrap); while ((arg = va_arg (args, const gchar *))) - g_ptr_array_add (bwrap->argv, g_strdup (arg)); + flatpak_bwrap_add_arg (bwrap, arg); va_end (args); } @@ -125,6 +171,46 @@ other_array->len); } +static int * +flatpak_bwrap_steal_fds (FlatpakBwrap *bwrap, + gsize *len_out) +{ + gsize len = bwrap->fds->len; + int *res = (int *)g_array_free (bwrap->fds, FALSE); + + bwrap->fds = g_array_new (FALSE, TRUE, sizeof (int)); + *len_out = len; + return res; +} + +void +flatpak_bwrap_append_bwrap (FlatpakBwrap *bwrap, + FlatpakBwrap *other) +{ + g_autofree int *fds = NULL; + gsize n_fds, i; + + fds = flatpak_bwrap_steal_fds (other, &n_fds); + for (i = 0; i < n_fds; i++) + flatpak_bwrap_add_fd (bwrap, fds[i]); + + flatpak_bwrap_append_argsv (bwrap, + (char **)other->argv->pdata, + other->argv->len); + + for (i = 0; other->envp[i] != NULL; i++) + { + char *key_val = other->envp[i]; + char *eq = strchr (key_val, '='); + if (eq) + { + g_autofree char *key = g_strndup (key_val, eq - key_val); + flatpak_bwrap_set_env (bwrap, + key, eq + 1, TRUE); + } + } +} + void flatpak_bwrap_add_args_data_fd (FlatpakBwrap *bwrap, const char *op, @@ -133,7 +219,7 @@ { g_autofree char *fd_str = g_strdup_printf ("%d", fd); - g_array_append_val (bwrap->fds, fd); + flatpak_bwrap_add_fd (bwrap, fd); flatpak_bwrap_add_args (bwrap, op, fd_str, path_optional, NULL); @@ -185,3 +271,81 @@ flatpak_bwrap_add_args (bwrap, type, src, dest_real, NULL); } } + +gboolean +flatpak_bwrap_bundle_args (FlatpakBwrap *bwrap, + int start, + int end, + gboolean one_arg, + GError **error) +{ + gchar *data; + gchar *ptr; + gint i; + gsize data_len = 0; + int fd; + g_auto(GLnxTmpfile) args_tmpf = { 0, }; + + if (end == -1) + end = bwrap->argv->len; + + for (i = start; i < end; i++) + data_len += strlen (bwrap->argv->pdata[i]) + 1; + + data = g_new (gchar, data_len); + *data = 0; + ptr = data; + for (i = start; i < end; i++) + ptr = g_stpcpy (ptr, bwrap->argv->pdata[i]) + 1; + + if (!flatpak_buffer_to_sealed_memfd_or_tmpfile (&args_tmpf, "bwrap-args", data, data_len, error)) + return FALSE; + + fd = glnx_steal_fd (&args_tmpf.fd); + + { + g_autofree char *commandline = flatpak_quote_argv ((const char **) bwrap->argv->pdata + start, end - start); + flatpak_debug2 ("bwrap --args %d = %s", fd, commandline); + } + + flatpak_bwrap_add_fd (bwrap, fd); + g_ptr_array_remove_range (bwrap->argv, start, end - start); + if (one_arg) + { + g_ptr_array_insert (bwrap->argv, start, g_strdup_printf ("--args=%d", fd)); + } + else + { + g_ptr_array_insert (bwrap->argv, start, g_strdup ("--args")); + g_ptr_array_insert (bwrap->argv, start+1, g_strdup_printf ("%d", fd)); + } + + return TRUE; +} + +/* Unset FD_CLOEXEC on the array of fds passed in @user_data */ +void +flatpak_bwrap_child_setup_cb (gpointer user_data) +{ + GArray *fd_array = user_data; + int i; + + /* If no fd_array was specified, don't care. */ + if (fd_array == NULL) + return; + + /* Otherwise, mark not - close-on-exec all the fds in the array */ + for (i = 0; i < fd_array->len; i++) + { + int fd = g_array_index (fd_array, int, i); + + /* We also seek all fds to the start, because this lets + us use the same fd_array multiple times */ + if (lseek (fd, 0, SEEK_SET) < 0) + { + /* Ignore the error, this happens on e.g. pipe fds */ + } + + fcntl (fd, F_SETFD, 0); + } +} diff -Nru flatpak-0.11.7/common/flatpak-bwrap.h flatpak-0.11.8.3/common/flatpak-bwrap.h --- flatpak-0.11.7/common/flatpak-bwrap.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-bwrap.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,63 +0,0 @@ -/* - * Copyright © 2014-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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_BWRAP_H__ -#define __FLATPAK_BWRAP_H__ - -typedef struct { - GPtrArray *argv; - GArray *fds; - GStrv envp; -} FlatpakBwrap; - -FlatpakBwrap *flatpak_bwrap_new (char **env); -void flatpak_bwrap_free (FlatpakBwrap *bwrap); -void flatpak_bwrap_set_env (FlatpakBwrap *bwrap, - const char *variable, - const char *value, - gboolean overwrite); -void flatpak_bwrap_unset_env (FlatpakBwrap *bwrap, - const char *variable); -void flatpak_bwrap_add_args (FlatpakBwrap *bwrap, - ...); -void flatpak_bwrap_append_argsv (FlatpakBwrap *bwrap, - char **args, - int len); -void flatpak_bwrap_append_args (FlatpakBwrap *bwrap, - GPtrArray *other_array); -void flatpak_bwrap_add_args_data_fd (FlatpakBwrap *bwrap, - const char *op, - int fd, - const char *path_optional); -gboolean flatpak_bwrap_add_args_data (FlatpakBwrap *bwrap, - const char *name, - const char *content, - gssize content_size, - const char *path, - GError **error); -void flatpak_bwrap_add_bind_arg (FlatpakBwrap *bwrap, - const char *type, - const char *src, - const char *dest); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakBwrap, flatpak_bwrap_free) - - -#endif /* __FLATPAK_BWRAP_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-bwrap-private.h flatpak-0.11.8.3/common/flatpak-bwrap-private.h --- flatpak-0.11.7/common/flatpak-bwrap-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-bwrap-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright © 2014-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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_BWRAP_H__ +#define __FLATPAK_BWRAP_H__ + +typedef struct { + GPtrArray *argv; + GArray *noinherit_fds; /* Just keep these open while the bwrap lives */ + GArray *fds; + GStrv envp; +} FlatpakBwrap; + +extern char *flatpak_bwrap_empty_env[1]; + +FlatpakBwrap *flatpak_bwrap_new (char **env); +void flatpak_bwrap_free (FlatpakBwrap *bwrap); +void flatpak_bwrap_set_env (FlatpakBwrap *bwrap, + const char *variable, + const char *value, + gboolean overwrite); +gboolean flatpak_bwrap_is_empty (FlatpakBwrap *bwrap); +void flatpak_bwrap_finish (FlatpakBwrap *bwrap); +void flatpak_bwrap_unset_env (FlatpakBwrap *bwrap, + const char *variable); +void flatpak_bwrap_add_arg (FlatpakBwrap *bwrap, + const char *arg); +void flatpak_bwrap_add_noinherit_fd (FlatpakBwrap *bwrap, + int fd); +void flatpak_bwrap_add_fd (FlatpakBwrap *bwrap, + int fd); +void flatpak_bwrap_add_args (FlatpakBwrap *bwrap, + ...); +void flatpak_bwrap_add_arg_printf (FlatpakBwrap *bwrap, + const char *format, + ...) G_GNUC_PRINTF (2, 3); +void flatpak_bwrap_append_argsv (FlatpakBwrap *bwrap, + char **args, + int len); +void flatpak_bwrap_append_bwrap (FlatpakBwrap *bwrap, + FlatpakBwrap *other); /* Steals the fds */ +void flatpak_bwrap_append_args (FlatpakBwrap *bwrap, + GPtrArray *other_array); +void flatpak_bwrap_add_args_data_fd (FlatpakBwrap *bwrap, + const char *op, + int fd, + const char *path_optional); +gboolean flatpak_bwrap_add_args_data (FlatpakBwrap *bwrap, + const char *name, + const char *content, + gssize content_size, + const char *path, + GError **error); +void flatpak_bwrap_add_bind_arg (FlatpakBwrap *bwrap, + const char *type, + const char *src, + const char *dest); +gboolean flatpak_bwrap_bundle_args (FlatpakBwrap *bwrap, + int start, + int end, + gboolean one_arg, + GError **error); + +void flatpak_bwrap_child_setup_cb (gpointer user_data); + + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakBwrap, flatpak_bwrap_free) + + +#endif /* __FLATPAK_BWRAP_H__ */ diff -Nru flatpak-0.11.7/common/flatpak.c flatpak-0.11.8.3/common/flatpak.c --- flatpak-0.11.7/common/flatpak.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,3 @@ +#include "config.h" + +#include "flatpak-version-macros.h" diff -Nru flatpak-0.11.7/common/flatpak-chain-input-stream.c flatpak-0.11.8.3/common/flatpak-chain-input-stream.c --- flatpak-0.11.7/common/flatpak-chain-input-stream.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-chain-input-stream.c 2018-05-30 13:58:57.000000000 +0100 @@ -20,7 +20,7 @@ #include "config.h" -#include "flatpak-chain-input-stream.h" +#include "flatpak-chain-input-stream-private.h" enum { PROP_0, diff -Nru flatpak-0.11.7/common/flatpak-chain-input-stream.h flatpak-0.11.8.3/common/flatpak-chain-input-stream.h --- flatpak-0.11.7/common/flatpak-chain-input-stream.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-chain-input-stream.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,68 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#ifndef __GI_SCANNER__ - -#include - -G_BEGIN_DECLS - -#define FLATPAK_TYPE_CHAIN_INPUT_STREAM (flatpak_chain_input_stream_get_type ()) -#define FLATPAK_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStream)) -#define FLATPAK_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass)) -#define FLATPAK_IS_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM)) -#define FLATPAK_IS_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM)) -#define FLATPAK_CHAIN_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass)) - -typedef struct _FlatpakChainInputStream FlatpakChainInputStream; -typedef struct _FlatpakChainInputStreamClass FlatpakChainInputStreamClass; -typedef struct _FlatpakChainInputStreamPrivate FlatpakChainInputStreamPrivate; - -struct _FlatpakChainInputStream -{ - GInputStream parent_instance; - - /*< private >*/ - FlatpakChainInputStreamPrivate *priv; -}; - -struct _FlatpakChainInputStreamClass -{ - GInputStreamClass parent_class; - - /*< private >*/ - /* Padding for future expansion */ - void (*_g_reserved1) (void); - void (*_g_reserved2) (void); - void (*_g_reserved3) (void); - void (*_g_reserved4) (void); - void (*_g_reserved5) (void); -}; - -GType flatpak_chain_input_stream_get_type (void) G_GNUC_CONST; - -FlatpakChainInputStream * flatpak_chain_input_stream_new (GPtrArray *streams); - -G_END_DECLS - -#endif diff -Nru flatpak-0.11.7/common/flatpak-chain-input-stream-private.h flatpak-0.11.8.3/common/flatpak-chain-input-stream-private.h --- flatpak-0.11.7/common/flatpak-chain-input-stream-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-chain-input-stream-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,68 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#ifndef __GI_SCANNER__ + +#include + +G_BEGIN_DECLS + +#define FLATPAK_TYPE_CHAIN_INPUT_STREAM (flatpak_chain_input_stream_get_type ()) +#define FLATPAK_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStream)) +#define FLATPAK_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass)) +#define FLATPAK_IS_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM)) +#define FLATPAK_IS_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM)) +#define FLATPAK_CHAIN_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass)) + +typedef struct _FlatpakChainInputStream FlatpakChainInputStream; +typedef struct _FlatpakChainInputStreamClass FlatpakChainInputStreamClass; +typedef struct _FlatpakChainInputStreamPrivate FlatpakChainInputStreamPrivate; + +struct _FlatpakChainInputStream +{ + GInputStream parent_instance; + + /*< private >*/ + FlatpakChainInputStreamPrivate *priv; +}; + +struct _FlatpakChainInputStreamClass +{ + GInputStreamClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved1) (void); + void (*_g_reserved2) (void); + void (*_g_reserved3) (void); + void (*_g_reserved4) (void); + void (*_g_reserved5) (void); +}; + +GType flatpak_chain_input_stream_get_type (void) G_GNUC_CONST; + +FlatpakChainInputStream * flatpak_chain_input_stream_new (GPtrArray *streams); + +G_END_DECLS + +#endif diff -Nru flatpak-0.11.7/common/flatpak-common-types.h flatpak-0.11.8.3/common/flatpak-common-types.h --- flatpak-0.11.7/common/flatpak-common-types.h 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-common-types.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,35 +0,0 @@ -/* - * Copyright © 2015 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_COMMON_TYPES_H__ -#define __FLATPAK_COMMON_TYPES_H__ - -typedef enum { - FLATPAK_KINDS_APP = 1 << 0, - FLATPAK_KINDS_RUNTIME = 1 << 1, -} FlatpakKinds; - -typedef struct FlatpakDir FlatpakDir; -typedef struct FlatpakDeploy FlatpakDeploy; -typedef struct FlatpakOciRegistry FlatpakOciRegistry; -typedef struct _FlatpakOciManifest FlatpakOciManifest; -typedef struct FlatpakCompletion FlatpakCompletion; - -#endif /* __FLATPAK_COMMON_TYPES_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-common-types-private.h flatpak-0.11.8.3/common/flatpak-common-types-private.h --- flatpak-0.11.7/common/flatpak-common-types-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-common-types-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_COMMON_TYPES_H__ +#define __FLATPAK_COMMON_TYPES_H__ + +typedef enum { + FLATPAK_KINDS_APP = 1 << 0, + FLATPAK_KINDS_RUNTIME = 1 << 1, +} FlatpakKinds; + +typedef enum { + FLATPAK_RUN_FLAG_DEVEL = (1 << 0), + FLATPAK_RUN_FLAG_BACKGROUND = (1 << 1), + FLATPAK_RUN_FLAG_LOG_SESSION_BUS = (1 << 2), + FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS = (1 << 3), + FLATPAK_RUN_FLAG_NO_SESSION_HELPER = (1 << 4), + FLATPAK_RUN_FLAG_MULTIARCH = (1 << 5), + FLATPAK_RUN_FLAG_WRITABLE_ETC = (1 << 6), + FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY = (1 << 7), + FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY = (1 << 8), + FLATPAK_RUN_FLAG_SET_PERSONALITY = (1 << 9), + FLATPAK_RUN_FLAG_FILE_FORWARDING = (1 << 10), + FLATPAK_RUN_FLAG_DIE_WITH_PARENT = (1 << 11), + FLATPAK_RUN_FLAG_LOG_A11Y_BUS = (1 << 12), + FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY = (1 << 13), + FLATPAK_RUN_FLAG_SANDBOX = (1 << 14), + FLATPAK_RUN_FLAG_NO_DOCUMENTS_PORTAL = (1 << 15), + FLATPAK_RUN_FLAG_BLUETOOTH = (1 << 16), +} FlatpakRunFlags; + +typedef struct FlatpakDir FlatpakDir; +typedef struct FlatpakDeploy FlatpakDeploy; +typedef struct FlatpakOciRegistry FlatpakOciRegistry; +typedef struct _FlatpakOciManifest FlatpakOciManifest; +typedef struct FlatpakCompletion FlatpakCompletion; + +#endif /* __FLATPAK_COMMON_TYPES_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-context.c flatpak-0.11.8.3/common/flatpak-context.c --- flatpak-0.11.7/common/flatpak-context.c 2018-04-30 13:33:48.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-context.c 2018-06-11 14:52:37.000000000 +0100 @@ -37,12 +37,12 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-run.h" +#include "flatpak-run-private.h" #include "flatpak-proxy.h" -#include "flatpak-utils.h" -#include "flatpak-dir.h" -#include "flatpak-systemd-dbus.h" -#include "lib/flatpak-error.h" +#include "flatpak-utils-private.h" +#include "flatpak-dir-private.h" +#include "flatpak-systemd-dbus-generated.h" +#include "flatpak-error.h" /* Same order as enum */ const char *flatpak_context_shares[] = { @@ -72,6 +72,7 @@ const char *flatpak_context_features[] = { "devel", "multiarch", + "bluetooth", NULL }; @@ -195,7 +196,7 @@ static FlatpakPolicy flatpak_policy_from_string (const char *string, GError **error) { - const char *policies[] = { "none", "see", "filtered", "talk", "own", NULL }; + const char *policies[] = { "none", "see", "talk", "own", NULL }; int i; g_autofree char *values = NULL; @@ -245,7 +246,7 @@ return TRUE; g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, - _("Invalid dbus name %s\n"), name); + _("Invalid dbus name %s"), name); return FALSE; } @@ -1187,10 +1188,10 @@ { NULL } }; -void -flatpak_context_complete (FlatpakContext *context, FlatpakCompletion *completion) +GOptionEntry * +flatpak_context_get_option_entries (void) { - flatpak_complete_options (completion, context_options); + return context_options; } GOptionGroup * @@ -1764,30 +1765,30 @@ flatpak_context_add_bus_filters (FlatpakContext *context, const char *app_id, gboolean session_bus, - GPtrArray *dbus_proxy_argv) + FlatpakBwrap *bwrap) { GHashTable *ht; GHashTableIter iter; gpointer key, value; - g_ptr_array_add (dbus_proxy_argv, g_strdup ("--filter")); + flatpak_bwrap_add_arg (bwrap, "--filter"); if (app_id && session_bus) - { - 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)); - } + flatpak_bwrap_add_arg_printf (bwrap, "--own=%s.*", app_id); if (session_bus) ht = context->session_bus_policy; else ht = context->system_bus_policy; + g_hash_table_iter_init (&iter, ht); while (g_hash_table_iter_next (&iter, &key, &value)) { FlatpakPolicy policy = GPOINTER_TO_INT (value); if (policy > 0) - g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--%s=%s", flatpak_policy_to_string (policy), (char *) key)); + flatpak_bwrap_add_arg_printf (bwrap, "--%s=%s", + flatpak_policy_to_string (policy), + (char *) key); } } @@ -1969,6 +1970,23 @@ return g_steal_pointer (&exports); } +FlatpakRunFlags +flatpak_context_get_run_flags (FlatpakContext *context) +{ + FlatpakRunFlags flags = 0; + + if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_DEVEL)) + flags |= FLATPAK_RUN_FLAG_DEVEL; + + if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_MULTIARCH)) + flags |= FLATPAK_RUN_FLAG_MULTIARCH; + + if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_BLUETOOTH)) + flags |= FLATPAK_RUN_FLAG_BLUETOOTH; + + return flags; +} + void flatpak_context_append_bwrap_filesystem (FlatpakContext *context, FlatpakBwrap *bwrap, diff -Nru flatpak-0.11.7/common/flatpak-context.h flatpak-0.11.8.3/common/flatpak-context.h --- flatpak-0.11.7/common/flatpak-context.h 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-context.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,131 +0,0 @@ -/* - * Copyright © 2014-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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_CONTEXT_H__ -#define __FLATPAK_CONTEXT_H__ - -#include "libglnx/libglnx.h" -#include "dbus-proxy/flatpak-proxy.h" -#include -#include "flatpak-exports.h" - -typedef struct FlatpakContext FlatpakContext; - -typedef enum { - FLATPAK_CONTEXT_SHARED_NETWORK = 1 << 0, - FLATPAK_CONTEXT_SHARED_IPC = 1 << 1, -} FlatpakContextShares; - -typedef enum { - FLATPAK_CONTEXT_SOCKET_X11 = 1 << 0, - FLATPAK_CONTEXT_SOCKET_WAYLAND = 1 << 1, - FLATPAK_CONTEXT_SOCKET_PULSEAUDIO = 1 << 2, - FLATPAK_CONTEXT_SOCKET_SESSION_BUS = 1 << 3, - FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS = 1 << 4, - FLATPAK_CONTEXT_SOCKET_FALLBACK_X11 = 1 << 5, /* For backwards compat, also set SOCKET_X11 */ -} FlatpakContextSockets; - -typedef enum { - FLATPAK_CONTEXT_DEVICE_DRI = 1 << 0, - FLATPAK_CONTEXT_DEVICE_ALL = 1 << 1, - FLATPAK_CONTEXT_DEVICE_KVM = 1 << 2, -} FlatpakContextDevices; - -typedef enum { - FLATPAK_CONTEXT_FEATURE_DEVEL = 1 << 0, - FLATPAK_CONTEXT_FEATURE_MULTIARCH = 1 << 1, -} FlatpakContextFeatures; - -struct FlatpakContext -{ - FlatpakContextShares shares; - FlatpakContextShares shares_valid; - FlatpakContextSockets sockets; - FlatpakContextSockets sockets_valid; - FlatpakContextDevices devices; - FlatpakContextDevices devices_valid; - FlatpakContextFeatures features; - FlatpakContextFeatures features_valid; - GHashTable *env_vars; - GHashTable *persistent; - GHashTable *filesystems; - GHashTable *session_bus_policy; - GHashTable *system_bus_policy; - GHashTable *generic_policy; -}; - -extern const char *flatpak_context_sockets[]; -extern const char *flatpak_context_devices[]; -extern const char *flatpak_context_features[]; -extern const char *flatpak_context_shares[]; - -FlatpakContext *flatpak_context_new (void); -void flatpak_context_free (FlatpakContext *context); -void flatpak_context_merge (FlatpakContext *context, - FlatpakContext *other); -GOptionGroup *flatpak_context_get_options (FlatpakContext *context); -void flatpak_context_complete (FlatpakContext *context, - FlatpakCompletion *completion); -gboolean flatpak_context_load_metadata (FlatpakContext *context, - GKeyFile *metakey, - GError **error); -void flatpak_context_save_metadata (FlatpakContext *context, - gboolean flatten, - GKeyFile *metakey); -void flatpak_context_allow_host_fs (FlatpakContext *context); -void flatpak_context_set_session_bus_policy (FlatpakContext *context, - const char *name, - FlatpakPolicy policy); -GStrv flatpak_context_get_session_bus_policy_allowed_own_names (FlatpakContext *context); -void flatpak_context_set_system_bus_policy (FlatpakContext *context, - const char *name, - FlatpakPolicy policy); -void flatpak_context_to_args (FlatpakContext *context, - GPtrArray *args); -void flatpak_context_add_bus_filters (FlatpakContext *context, - const char *app_id, - gboolean session_bus, - GPtrArray *dbus_proxy_argv); - -gboolean flatpak_context_get_needs_session_bus_proxy (FlatpakContext *context); -gboolean flatpak_context_get_needs_system_bus_proxy (FlatpakContext *context); - -void flatpak_context_make_sandboxed (FlatpakContext *context); - -gboolean flatpak_context_allows_features (FlatpakContext *context, - FlatpakContextFeatures features); - -FlatpakContext *flatpak_context_load_for_deploy (FlatpakDeploy *deploy, - GError **error); -FlatpakContext *flatpak_context_load_for_app (const char *app_id, - GError **error); - -FlatpakExports *flatpak_context_get_exports (FlatpakContext *context, - const char *app_id); - -void flatpak_context_append_bwrap_filesystem (FlatpakContext *context, - FlatpakBwrap *bwrap, - const char *app_id, - GFile *app_id_dir, - FlatpakExports **exports_out); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakContext, flatpak_context_free) - -#endif /* __FLATPAK_CONTEXT_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-context-private.h flatpak-0.11.8.3/common/flatpak-context-private.h --- flatpak-0.11.7/common/flatpak-context-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-context-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,132 @@ +/* + * Copyright © 2014-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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_CONTEXT_H__ +#define __FLATPAK_CONTEXT_H__ + +#include "libglnx/libglnx.h" +#include "dbus-proxy/flatpak-proxy.h" +#include +#include "flatpak-exports-private.h" + +typedef struct FlatpakContext FlatpakContext; + +typedef enum { + FLATPAK_CONTEXT_SHARED_NETWORK = 1 << 0, + FLATPAK_CONTEXT_SHARED_IPC = 1 << 1, +} FlatpakContextShares; + +typedef enum { + FLATPAK_CONTEXT_SOCKET_X11 = 1 << 0, + FLATPAK_CONTEXT_SOCKET_WAYLAND = 1 << 1, + FLATPAK_CONTEXT_SOCKET_PULSEAUDIO = 1 << 2, + FLATPAK_CONTEXT_SOCKET_SESSION_BUS = 1 << 3, + FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS = 1 << 4, + FLATPAK_CONTEXT_SOCKET_FALLBACK_X11 = 1 << 5, /* For backwards compat, also set SOCKET_X11 */ +} FlatpakContextSockets; + +typedef enum { + FLATPAK_CONTEXT_DEVICE_DRI = 1 << 0, + FLATPAK_CONTEXT_DEVICE_ALL = 1 << 1, + FLATPAK_CONTEXT_DEVICE_KVM = 1 << 2, +} FlatpakContextDevices; + +typedef enum { + FLATPAK_CONTEXT_FEATURE_DEVEL = 1 << 0, + FLATPAK_CONTEXT_FEATURE_MULTIARCH = 1 << 1, + FLATPAK_CONTEXT_FEATURE_BLUETOOTH = 1 << 2, +} FlatpakContextFeatures; + +struct FlatpakContext +{ + FlatpakContextShares shares; + FlatpakContextShares shares_valid; + FlatpakContextSockets sockets; + FlatpakContextSockets sockets_valid; + FlatpakContextDevices devices; + FlatpakContextDevices devices_valid; + FlatpakContextFeatures features; + FlatpakContextFeatures features_valid; + GHashTable *env_vars; + GHashTable *persistent; + GHashTable *filesystems; + GHashTable *session_bus_policy; + GHashTable *system_bus_policy; + GHashTable *generic_policy; +}; + +extern const char *flatpak_context_sockets[]; +extern const char *flatpak_context_devices[]; +extern const char *flatpak_context_features[]; +extern const char *flatpak_context_shares[]; + +FlatpakContext *flatpak_context_new (void); +void flatpak_context_free (FlatpakContext *context); +void flatpak_context_merge (FlatpakContext *context, + FlatpakContext *other); +GOptionEntry *flatpak_context_get_option_entries (void); +GOptionGroup *flatpak_context_get_options (FlatpakContext *context); +gboolean flatpak_context_load_metadata (FlatpakContext *context, + GKeyFile *metakey, + GError **error); +void flatpak_context_save_metadata (FlatpakContext *context, + gboolean flatten, + GKeyFile *metakey); +void flatpak_context_allow_host_fs (FlatpakContext *context); +void flatpak_context_set_session_bus_policy (FlatpakContext *context, + const char *name, + FlatpakPolicy policy); +GStrv flatpak_context_get_session_bus_policy_allowed_own_names (FlatpakContext *context); +void flatpak_context_set_system_bus_policy (FlatpakContext *context, + const char *name, + FlatpakPolicy policy); +void flatpak_context_to_args (FlatpakContext *context, + GPtrArray *args); +FlatpakRunFlags flatpak_context_get_run_flags (FlatpakContext *context); +void flatpak_context_add_bus_filters (FlatpakContext *context, + const char *app_id, + gboolean session_bus, + FlatpakBwrap *bwrap); + +gboolean flatpak_context_get_needs_session_bus_proxy (FlatpakContext *context); +gboolean flatpak_context_get_needs_system_bus_proxy (FlatpakContext *context); + +void flatpak_context_make_sandboxed (FlatpakContext *context); + +gboolean flatpak_context_allows_features (FlatpakContext *context, + FlatpakContextFeatures features); + +FlatpakContext *flatpak_context_load_for_deploy (FlatpakDeploy *deploy, + GError **error); +FlatpakContext *flatpak_context_load_for_app (const char *app_id, + GError **error); + +FlatpakExports *flatpak_context_get_exports (FlatpakContext *context, + const char *app_id); + +void flatpak_context_append_bwrap_filesystem (FlatpakContext *context, + FlatpakBwrap *bwrap, + const char *app_id, + GFile *app_id_dir, + FlatpakExports **exports_out); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakContext, flatpak_context_free) + +#endif /* __FLATPAK_CONTEXT_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-dir.c flatpak-0.11.8.3/common/flatpak-dir.c --- flatpak-0.11.7/common/flatpak-dir.c 2018-05-03 07:22:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-dir.c 2018-06-11 15:11:47.000000000 +0100 @@ -38,13 +38,13 @@ #include #include #include "libglnx/libglnx.h" -#include "lib/flatpak-error.h" +#include "flatpak-error.h" #include -#include "flatpak-dir.h" -#include "flatpak-utils.h" -#include "flatpak-oci-registry.h" -#include "flatpak-run.h" +#include "flatpak-dir-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-oci-registry-private.h" +#include "flatpak-run-private.h" #include "errno.h" @@ -235,28 +235,39 @@ return TRUE; } - -char * +/* Returns TRUE if the ref is found in the summary or cache. out_checksum and + * out_variant are not guaranteed to be set even when the ref is found. */ +gboolean flatpak_remote_state_lookup_ref (FlatpakRemoteState *self, const char *ref, + char **out_checksum, GVariant **out_variant, GError **error) { - g_autofree char *latest_rev = NULL; - - if (!flatpak_remote_state_ensure_summary (self, error)) - return NULL; + if (self->collection_id == NULL || self->summary != NULL) + { + if (!flatpak_remote_state_ensure_summary (self, error)) + return FALSE; - if (!flatpak_summary_lookup_ref (self->summary, self->collection_id, ref, &latest_rev, out_variant)) + if (!flatpak_summary_lookup_ref (self->summary, self->collection_id, ref, out_checksum, out_variant)) + { + if (self->collection_id != NULL) + flatpak_fail (error, "No such ref (%s, %s) in remote %s", self->collection_id, ref, self->remote_name); + else + flatpak_fail (error, "No such ref '%s' in remote %s", ref, self->remote_name); + return FALSE; + } + } + else { - if (self->collection_id != NULL) - flatpak_fail (error, "No such ref (%s, %s) in remote %s", self->collection_id, ref, self->remote_name); - else - flatpak_fail (error, "No such ref '%s' in remote %s", ref, self->remote_name); - return NULL; + if (!flatpak_remote_state_ensure_metadata (self, error)) + return FALSE; + + if (!flatpak_remote_state_lookup_cache (self, ref, NULL, NULL, NULL, error)) + return FALSE; } - return g_steal_pointer (&latest_rev); + return TRUE; } char ** @@ -321,8 +332,8 @@ cache_v = g_variant_lookup_value (self->metadata, "xa.cache", NULL); if (cache_v == NULL) { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - _("No flatpak cache in remote summary")); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + _("No flatpak cache in remote '%s' summary"), self->remote_name); return FALSE; } @@ -331,7 +342,7 @@ if (!flatpak_variant_bsearch_str (cache, ref, &pos)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - _("No entry for %s in remote summary flatpak cache "), ref); + _("No entry for %s in remote '%s' summary flatpak cache "), ref, self->remote_name); return FALSE; } @@ -939,14 +950,6 @@ return NULL; } - if (setxattr (path, "user.test", "novalue", strlen ("novalue"), 0) < 0 && - (errno == ENOTSUP || errno == EOPNOTSUPP)) - { - flatpak_fail (error, - _("/var/tmp does not suport xattrs which is needed for system-wide installation as a user. FLATPAK_SYSTEM_CACHE_DIR can be used to set an alternative path.")); - return NULL; - } - unlink (symlink_path); if (symlink (path, symlink_path) != 0) { @@ -1607,6 +1610,17 @@ return eol; } +const char * +flatpak_deploy_data_get_runtime (GVariant *deploy_data) +{ + g_autoptr(GVariant) metadata = g_variant_get_child_value (deploy_data, 4); + const char *runtime = NULL; + + g_variant_lookup (metadata, "runtime", "&s", &runtime); + + return runtime; +} + /** * flatpak_deploy_data_get_subpaths: * @@ -1898,13 +1912,9 @@ if (!g_file_query_exists (repodir, cancellable)) { + /* We always use bare-user-only these days, except old installations + that still user bare-user */ OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER_ONLY; - const char *mode_env = g_getenv ("FLATPAK_OSTREE_REPO_MODE"); - - if (g_strcmp0 (mode_env, "user-only") == 0) - mode = OSTREE_REPO_MODE_BARE_USER_ONLY; - if (g_strcmp0 (mode_env, "user") == 0) - mode = OSTREE_REPO_MODE_BARE_USER; if (!ostree_repo_create (repo, mode, cancellable, &my_error)) { @@ -2314,13 +2324,13 @@ /* Find the latest rev from the remote and its available mirrors, including * LAN and USB sources. */ g_auto(GVariantBuilder) find_builder = FLATPAK_VARIANT_BUILDER_INITIALIZER; - g_autoptr(GMainContext) context = NULL; g_autoptr(GVariant) find_options = NULL; g_autoptr(GAsyncResult) find_result = NULL; g_auto(OstreeRepoFinderResultv) results = NULL; OstreeCollectionRef collection_ref = { state->collection_id, (char *) ref }; OstreeCollectionRef *collection_refs_to_fetch[2] = { &collection_ref, NULL }; gsize i; + g_autoptr(GMainContextPopDefault) context = NULL; /* Find options */ g_variant_builder_init (&find_builder, G_VARIANT_TYPE ("a{sv}")); @@ -2333,8 +2343,7 @@ find_options = g_variant_ref_sink (g_variant_builder_end (&find_builder)); - context = g_main_context_new (); - g_main_context_push_thread_default (context); + context = flatpak_main_context_new_default (); ostree_repo_find_remotes_async (self->repo, (const OstreeCollectionRef * const *) collection_refs_to_fetch, find_options, @@ -2346,6 +2355,7 @@ g_main_context_iteration (context, TRUE); results = ostree_repo_find_remotes_finish (self->repo, find_result, error); + if (results == NULL) return FALSE; @@ -2371,9 +2381,14 @@ } else { - latest_rev = flatpak_remote_state_lookup_ref (state, ref, NULL, error); + flatpak_remote_state_lookup_ref (state, ref, &latest_rev, NULL, error); if (latest_rev == NULL) - return FALSE; + { + if (error != NULL && *error == NULL) + flatpak_fail (error, "Couldn't find latest checksum for ref %s in remote %s", + ref, state->remote_name); + return FALSE; + } if (out_rev != NULL) *out_rev = g_steal_pointer (&latest_rev); @@ -2662,6 +2677,7 @@ get_common_pull_options (GVariantBuilder *builder, const char *ref_to_fetch, const gchar * const *dirs_to_pull, + const char *current_local_checksum, gboolean force_disable_deltas, OstreeRepoPullFlags flags, OstreeAsyncProgress *progress) @@ -2691,6 +2707,8 @@ g_variant_builder_init (&hdr_builder, G_VARIANT_TYPE ("a(ss)")); g_variant_builder_add (&hdr_builder, "(ss)", "Flatpak-Ref", ref_to_fetch); + if (current_local_checksum) + g_variant_builder_add (&hdr_builder, "(ss)", "Flatpak-Upgrade-From", current_local_checksum); g_variant_builder_add (builder, "{s@v}", "http-headers", g_variant_new_variant (g_variant_builder_end (&hdr_builder))); g_variant_builder_add (builder, "{s@v}", "append-user-agent", @@ -2738,6 +2756,10 @@ /* We always want this on for every type of pull */ flags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES; + remote_and_branch = g_strdup_printf ("%s:%s", remote_name, ref_to_fetch); + if (!ostree_repo_resolve_rev (self, remote_and_branch, TRUE, ¤t_checksum, error)) + return FALSE; + if (!repo_get_remote_collection_id (self, remote_name, &collection_id, NULL)) g_clear_pointer (&collection_id, g_free); @@ -2746,12 +2768,12 @@ { GVariantBuilder find_builder, pull_builder; g_autoptr(GVariant) find_options = NULL, pull_options = NULL; - g_autoptr(GMainContext) context = NULL; g_autoptr(GAsyncResult) find_result = NULL, pull_result = NULL; g_auto(OstreeRepoFinderResultv) results = NULL; OstreeCollectionRef collection_ref; OstreeCollectionRef *collection_refs_to_fetch[2]; guint32 update_freq = 0; + g_autoptr(GMainContextPopDefault) context = NULL; /* Find options */ g_variant_builder_init (&find_builder, G_VARIANT_TYPE ("a{sv}")); @@ -2786,12 +2808,11 @@ /* Pull options */ g_variant_builder_init (&pull_builder, G_VARIANT_TYPE ("a{sv}")); - get_common_pull_options (&pull_builder, ref_to_fetch, dirs_to_pull, + get_common_pull_options (&pull_builder, ref_to_fetch, dirs_to_pull, current_checksum, force_disable_deltas, flags, progress); pull_options = g_variant_ref_sink (g_variant_builder_end (&pull_builder)); - context = g_main_context_new (); - g_main_context_push_thread_default (context); + context = flatpak_main_context_new_default (); if (results_to_fetch == NULL) { @@ -2821,8 +2842,6 @@ } else res = FALSE; - - g_main_context_pop_thread_default (context); } else res = FALSE; @@ -2843,7 +2862,7 @@ /* Pull options */ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - get_common_pull_options (&builder, ref_to_fetch, dirs_to_pull, + get_common_pull_options (&builder, ref_to_fetch, dirs_to_pull, current_checksum, force_disable_deltas, flags, progress); refs_to_fetch[0] = ref_to_fetch; @@ -2858,9 +2877,6 @@ options = g_variant_ref_sink (g_variant_builder_end (&builder)); - remote_and_branch = g_strdup_printf ("%s:%s", remote_name, ref_to_fetch); - if (!ostree_repo_resolve_rev (self, remote_and_branch, TRUE, ¤t_checksum, error)) - return FALSE; if (current_checksum != NULL && !ostree_repo_load_commit (self, current_checksum, &old_commit, NULL, error)) return FALSE; @@ -3296,9 +3312,14 @@ return FALSE; /* We use the summary so that we can reuse any cached json */ - latest_rev = flatpak_remote_state_lookup_ref (state, ref, &summary_element, error); + flatpak_remote_state_lookup_ref (state, ref, &latest_rev, &summary_element, error); if (latest_rev == NULL) - return FALSE; + { + if (error != NULL && *error == NULL) + flatpak_fail (error, "Couldn't find latest checksum for ref %s in remote %s", + ref, state->remote_name); + return FALSE; + } if (skip_if_current_is != NULL && strcmp (latest_rev, skip_if_current_is) == 0) { @@ -3383,10 +3404,14 @@ return FALSE; /* We use the summary so that we can reuse any cached json */ - latest_rev = - flatpak_remote_state_lookup_ref (state, ref, &summary_element, error); + flatpak_remote_state_lookup_ref (state, ref, &latest_rev, &summary_element, error); if (latest_rev == NULL) - return FALSE; + { + if (error != NULL && *error == NULL) + flatpak_fail (error, "Couldn't find latest checksum for ref %s in remote %s", + ref, state->remote_name); + return FALSE; + } metadata = g_variant_get_child_value (summary_element, 2); g_variant_lookup (metadata, "xa.oci-repository", "s", &oci_repository); @@ -3530,13 +3555,13 @@ { GVariantBuilder find_builder; g_autoptr(GVariant) find_options = NULL; - g_autoptr(GMainContext) context = NULL; g_autoptr(GAsyncResult) find_result = NULL; OstreeCollectionRef collection_ref; OstreeCollectionRef *collection_refs_to_fetch[2]; gboolean force_disable_deltas = (flatpak_flags & FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS) != 0; guint update_freq = 0; gsize i; + g_autoptr(GMainContextPopDefault) context = NULL; g_variant_builder_init (&find_builder, G_VARIANT_TYPE ("a{sv}")); @@ -3562,8 +3587,7 @@ find_options = g_variant_ref_sink (g_variant_builder_end (&find_builder)); - context = g_main_context_new (); - g_main_context_push_thread_default (context); + context = flatpak_main_context_new_default (); ostree_repo_find_remotes_async (self->repo, (const OstreeCollectionRef * const *) collection_refs_to_fetch, find_options, @@ -3575,8 +3599,6 @@ allocated_results = ostree_repo_find_remotes_finish (self->repo, find_result, error); - g_main_context_pop_thread_default (context); - results = (const OstreeRepoFinderResult * const *) allocated_results; if (results == NULL) return FALSE; @@ -3591,7 +3613,11 @@ else #endif /* FLATPAK_ENABLE_P2P */ { - rev = flatpak_remote_state_lookup_ref (state, ref, NULL, error); + flatpak_remote_state_lookup_ref (state, ref, &rev, NULL, error); + if (rev == NULL && error != NULL && *error == NULL) + flatpak_fail (error, "Couldn't find latest checksum for ref %s in remote %s", + ref, state->remote_name); + results = NULL; } @@ -3834,7 +3860,7 @@ { if (!g_file_load_contents (summary_sig_file, cancellable, &summary_sig_data, &summary_sig_data_size, NULL, NULL)) - return flatpak_fail (error, "GPG verification enabled, but no summary signatures found"); + return flatpak_fail (error, "GPG verification enabled, but no summary signatures found for remote '%s'", remote_name); summary_sig_bytes = g_bytes_new_take (summary_sig_data, summary_sig_data_size); @@ -3847,7 +3873,7 @@ return FALSE; if (ostree_gpg_verify_result_count_valid (gpg_result) == 0) - return flatpak_fail (error, "GPG signatures found, but none are in trusted keyring"); + return flatpak_fail (error, "GPG signatures found for remote '%s', but none are in trusted keyring", remote_name); } g_clear_object (&gpg_result); @@ -4315,6 +4341,36 @@ return ret; } +GVariant * +flatpak_dir_read_latest_commit (FlatpakDir *self, + const char *remote, + const char *ref, + GCancellable *cancellable, + GError **error) +{ + g_autofree char *remote_and_ref = NULL; + g_autofree char *res = NULL; + g_autoptr(GVariant) commit_data = NULL; + + /* There may be several remotes with the same branch (if we for + * instance changed the origin, so prepend the current origin to + * make sure we get the right one */ + + if (remote) + remote_and_ref = g_strdup_printf ("%s:%s", remote, ref); + else + remote_and_ref = g_strdup (ref); + + if (!ostree_repo_resolve_rev (self->repo, remote_and_ref, FALSE, &res, error)) + return NULL; + + if (!ostree_repo_load_commit (self->repo, res, &commit_data, NULL, error)) + return NULL; + + return g_steal_pointer (&commit_data); +} + + char * flatpak_dir_read_latest (FlatpakDir *self, const char *remote, @@ -4423,7 +4479,7 @@ return ret; } -static gboolean +gboolean flatpak_dir_run_triggers (FlatpakDir *self, GCancellable *cancellable, GError **error) @@ -4436,6 +4492,25 @@ GError *temp_error = NULL; const char *triggerspath; + if (flatpak_dir_use_system_helper (self, NULL)) + { + const char *installation = flatpak_dir_get_id (self); + FlatpakSystemHelper *system_helper = flatpak_dir_get_system_helper (self); + + /* If we don't have the system helper, we'll have to try as an + * unprivileged user, which might fail later */ + if (system_helper) + { + if (!flatpak_system_helper_call_run_triggers_sync (system_helper, + installation ? installation : "", + cancellable, + error)) + return FALSE; + } + + return TRUE; + } + triggerspath = g_getenv ("FLATPAK_TRIGGERSDIR"); if (triggerspath == NULL) triggerspath = FLATPAK_TRIGGERDIR; @@ -5333,9 +5408,6 @@ if (!flatpak_remove_dangling_symlinks (exports, cancellable, error)) goto out; - if (!flatpak_dir_run_triggers (self, cancellable, error)) - goto out; - ret = TRUE; out: @@ -5613,9 +5685,9 @@ app_context, NULL, NULL, cancellable, error)) return FALSE; - g_ptr_array_add (bwrap->argv, g_strdup ("/app/bin/apply_extra")); + flatpak_bwrap_add_arg (bwrap, "/app/bin/apply_extra"); - g_ptr_array_add (bwrap->argv, NULL); + flatpak_bwrap_finish (bwrap); g_debug ("Running /app/bin/apply_extra "); @@ -5693,6 +5765,9 @@ g_autoptr(GVariant) commit_metadata = NULL; GVariantBuilder metadata_builder; g_auto(GLnxLockFile) lock = { 0, }; + g_autoptr(GFile) metadata_file = NULL; + g_autofree char *metadata_contents = NULL; + g_autofree char *application_runtime = NULL; gboolean is_app; if (!flatpak_dir_ensure_repo (self, cancellable, error)) @@ -5936,18 +6011,32 @@ } } + metadata_file = g_file_resolve_relative_path (checkoutdir, "metadata"); + if (g_file_load_contents (metadata_file, NULL, + &metadata_contents, NULL, NULL, NULL)) + { + g_autoptr(GKeyFile) keyfile = g_key_file_new (); + if (!g_key_file_load_from_data (keyfile, + metadata_contents, + -1, + 0, error)) + return FALSE; + + application_runtime = g_key_file_get_string (keyfile, + FLATPAK_METADATA_GROUP_APPLICATION, + FLATPAK_METADATA_KEY_RUNTIME, NULL); + + if (!flatpak_check_required_version (ref, keyfile, error)) + return FALSE; + } + /* Check the metadata in the commit to make sure it matches the actual deployed metadata, in case we relied on the one in the commit for a decision */ g_variant_lookup (commit_metadata, "xa.metadata", "&s", &xa_metadata); if (xa_metadata != NULL) { - g_autoptr(GFile) metadata_file = g_file_resolve_relative_path (checkoutdir, "metadata"); - g_autofree char *metadata_contents = NULL; - - if (!g_file_load_contents (metadata_file, NULL, - &metadata_contents, NULL, NULL, NULL) || - strcmp (metadata_contents, xa_metadata) != 0) + if (g_strcmp0 (metadata_contents, xa_metadata) != 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("Deployed metadata does not match commit")); @@ -6070,6 +6159,9 @@ if (eol_rebase) g_variant_builder_add (&metadata_builder, "{s@v}", "eolr", g_variant_new_variant (g_variant_new_string (eol_rebase))); + if (application_runtime) + g_variant_builder_add (&metadata_builder, "{s@v}", "runtime", + g_variant_new_variant (g_variant_new_string (application_runtime))); deploy_data = flatpak_dir_new_deploy_data (origin, checksum, @@ -6356,13 +6448,20 @@ g_autofree char *tmpdir_name = NULL; g_autoptr(OstreeRepo) new_repo = NULL; g_autoptr(GKeyFile) config = NULL; - OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER; - const char *mode_str = "bare-user"; g_autofree char *current_mode = NULL; - const char *mode_env = g_getenv ("FLATPAK_OSTREE_REPO_MODE"); GKeyFile *orig_config = NULL; g_autofree char *orig_min_free_space_percent = NULL; + /* We use bare-user-only here now, which means we don't need xattrs + * for the child repo. This only works as long as the pulled repo + * is valid in a bare-user-only repo, i.e. doesn't have xattrs or + * weird permissions, because then the pull into the system repo + * would complain that the checksum was wrong. However, by now all + * flatpak builds are likely to be valid, so this is fine. + */ + OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER_ONLY; + const char *mode_str = "bare-user-only"; + g_assert (!self->user); if (!flatpak_dir_ensure_repo (self, NULL, error)) @@ -6387,12 +6486,6 @@ new_repo = ostree_repo_new (repo_dir); - /* Allow to override the mode when user-only is needed (e.g. live systems) */ - if (g_strcmp0 (mode_env, "user-only") == 0) { - mode = OSTREE_REPO_MODE_BARE_USER_ONLY; - mode_str = "bare-user-only"; - } - repo_dir_config = g_file_get_child (repo_dir, "config"); if (!g_file_query_exists (repo_dir_config, NULL)) { @@ -6731,6 +6824,59 @@ return g_steal_pointer (&remote); } +/* If core.add-remotes-config-dir is set for this repository (which is + * not a common configuration, but it is possible), we will fail to modify + * remote configuration when using a combination of + * ostree_repo_remote_[add|change]() and ostree_repo_write_config() due to + * adding remote config in /etc/flatpak/remotes.d and also in + * /ostree/repo/config. Avoid that. + * + * FIXME: See https://github.com/flatpak/flatpak/issues/1665. In future, we + * should just write the remote config to the correct place, factoring + * core.add-remotes-config-dir in. */ +static gboolean +flatpak_dir_check_add_remotes_config_dir (FlatpakDir *self, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + gboolean val; + GKeyFile *config; + + if (!flatpak_dir_maybe_ensure_repo (self, NULL, error)) + return FALSE; + + if (self->repo == NULL) + return TRUE; + + config = ostree_repo_get_config (self->repo); + + if (config == NULL) + return TRUE; + + val = g_key_file_get_boolean (config, "core", "add-remotes-config-dir", &local_error); + + if (local_error != NULL) + { + if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) + { + g_clear_error (&local_error); + val = ostree_repo_is_system (self->repo); + } + else + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + + if (!val) + return TRUE; + + return flatpak_fail (error, + "Can’t update remote configuration on a repository with " + "core.add-remotes-config-dir=true"); +} + gboolean flatpak_dir_install_bundle (FlatpakDir *self, GFile *file, @@ -6747,6 +6893,9 @@ g_autofree char *to_checksum = NULL; gboolean gpg_verify; + if (!flatpak_dir_check_add_remotes_config_dir (self, error)) + return FALSE; + if (flatpak_dir_use_system_helper (self, NULL)) { FlatpakSystemHelper *system_helper; @@ -6826,7 +6975,6 @@ /* The pull succeeded, and this is an update. So, we need to update the repo config if anything changed */ - ostree_repo_remote_get_url (self->repo, remote, &old_url, @@ -7241,6 +7389,37 @@ if (repository == NULL) return FALSE; + if (g_str_has_prefix (ref, "runtime/") && !force_remove) + { + g_auto(GStrv) app_refs = NULL; + g_autoptr(GPtrArray) blocking = g_ptr_array_new_with_free_func (g_free); + const char *pref = ref + strlen ("runtime/"); + int i; + + /* Look for apps that need this runtime */ + + flatpak_dir_list_refs (self, "app", &app_refs, NULL, NULL); + for (i = 0; app_refs != NULL && app_refs[i] != NULL; i++) + { + g_autoptr(GVariant) deploy_data = flatpak_dir_get_deploy_data (self, app_refs[i], NULL, NULL); + + if (deploy_data) + { + const char *app_runtime = flatpak_deploy_data_get_runtime (deploy_data); + + if (g_strcmp0 (app_runtime, pref) == 0) + g_ptr_array_add (blocking, g_strdup (app_refs[i] + strlen ("app/"))); + } + } + g_ptr_array_add (blocking, NULL); + + if (blocking->len > 1) + { + g_autofree char *joined = g_strjoinv (", ", (char **)blocking->pdata); + return flatpak_fail (error, "Can't remove %s, it is needed for: %s", pref, joined); + } + } + g_debug ("dropping active ref"); if (!flatpak_dir_set_active (self, ref, NULL, cancellable, error)) return FALSE; @@ -7697,7 +7876,6 @@ /** * flatpak_dir_remove_ref: - * * @self: a #FlatpakDir * @remote_name: the name of the remote * @ref: the flatpak ref to remove @@ -8186,8 +8364,7 @@ } if (summary == NULL) - return flatpak_fail (error, "Remote listing for %s not available; server has no summary file\n" \ - "Check the URL passed to remote-add was valid\n", name_or_uri); + return flatpak_fail (error, "Remote listing for %s not available; server has no summary file. Check the URL passed to remote-add was valid.", name_or_uri); if (!is_local) flatpak_dir_cache_summary (self, summary, summary_sig, name_or_uri, url); @@ -8203,6 +8380,7 @@ _flatpak_dir_get_remote_state (FlatpakDir *self, const char *remote_or_uri, gboolean optional, + gboolean local_only, GBytes *opt_summary, GBytes *opt_summary_sig, GCancellable *cancellable, @@ -8223,6 +8401,13 @@ if (!is_local && !repo_get_remote_collection_id (self->repo, remote_or_uri, &state->collection_id, error)) return NULL; + if (local_only) + { + flatpak_fail (&state->summary_fetch_error, "Internal error, local_only state"); + flatpak_fail (&state->metadata_fetch_error, "Internal error, local_only state"); + return g_steal_pointer (&state); + } + if (opt_summary) { if (opt_summary_sig) @@ -8326,7 +8511,7 @@ GCancellable *cancellable, GError **error) { - return _flatpak_dir_get_remote_state (self, remote, FALSE, NULL, NULL, cancellable, error); + return _flatpak_dir_get_remote_state (self, remote, FALSE, FALSE, NULL, NULL, cancellable, error); } /* This is an alternative way to get the state where the summary is @@ -8344,7 +8529,7 @@ GCancellable *cancellable, GError **error) { - return _flatpak_dir_get_remote_state (self, remote, FALSE, opt_summary, opt_summary_sig, cancellable, error); + return _flatpak_dir_get_remote_state (self, remote, FALSE, FALSE, opt_summary, opt_summary_sig, cancellable, error); } /* This is an alternative way to get the remote state that doesn't @@ -8361,7 +8546,19 @@ GCancellable *cancellable, GError **error) { - return _flatpak_dir_get_remote_state (self, remote, TRUE, NULL, NULL, cancellable, error); + return _flatpak_dir_get_remote_state (self, remote, TRUE, FALSE, NULL, NULL, cancellable, error); +} + + +/* This doesn't do any i/o at all, just keeps track of the local details like + remote and collection-id. Useful when doing no-pull operations */ +FlatpakRemoteState * +flatpak_dir_get_remote_state_local_only (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error) +{ + return _flatpak_dir_get_remote_state (self, remote, TRUE, TRUE, NULL, NULL, cancellable, error); } static gboolean @@ -8371,17 +8568,15 @@ { g_autoptr(GError) local_error = NULL; g_autoptr(FlatpakRemoteState) state = NULL; - g_autofree char *rev = NULL; - state = flatpak_dir_get_remote_state (self, remote, NULL, &local_error); + state = flatpak_dir_get_remote_state_optional (self, remote, NULL, &local_error); if (state == NULL) { g_debug ("Can't get state for remote %s: %s", remote, local_error->message); return FALSE; } - rev = flatpak_remote_state_lookup_ref (state, ref, NULL, NULL); - return rev != NULL; + return flatpak_remote_state_lookup_ref (state, ref, NULL, NULL, NULL); } static void @@ -8436,14 +8631,50 @@ const gchar *collection_id; GVariantIter iter; - if (!flatpak_remote_state_ensure_summary (state, error)) - return FALSE; - ret_all_refs = g_hash_table_new_full (flatpak_collection_ref_hash, flatpak_collection_ref_equal, (GDestroyNotify) flatpak_collection_ref_free, g_free); + /* If the remote has P2P enabled and we're offline, get the refs list from + * xa.cache in ostree-metadata (although it's inferior to the summary refs + * list in that it lacks checksums). */ + if (state->collection_id != NULL && state->summary == NULL) + { + g_autoptr(GVariant) xa_cache = NULL; + g_autoptr(GVariant) cache = NULL; + gsize i, n; + + if (!flatpak_remote_state_ensure_metadata (state, error)) + return FALSE; + + if (!flatpak_remote_state_lookup_repo_metadata (state, "xa.cache", "@*", &xa_cache)) + return flatpak_fail (error, _("No summary or Flatpak cache available for remote %s"), + state->remote_name); + + cache = g_variant_get_child_value (xa_cache, 0); + n = g_variant_n_children (cache); + for (i = 0; i < n; i++) + { + g_autoptr(GVariant) child = NULL; + g_autoptr(GVariant) cur_v = NULL; + g_autoptr(FlatpakCollectionRef) coll_ref = NULL; + const char *ref; + + child = g_variant_get_child_value (cache, i); + cur_v = g_variant_get_child_value (child, 0); + ref = g_variant_get_string (cur_v, NULL); + coll_ref = flatpak_collection_ref_new (state->collection_id, ref); + + g_hash_table_insert (ret_all_refs, g_steal_pointer (&coll_ref), NULL); + } + + goto out; + } + + if (!flatpak_remote_state_ensure_summary (state, error)) + return FALSE; + /* refs that match the main collection-id */ ref_map = g_variant_get_child_value (state->summary, 0); @@ -8465,6 +8696,7 @@ } +out: *out_all_refs = g_steal_pointer (&ret_all_refs); return TRUE; @@ -8664,7 +8896,7 @@ g_autoptr(FlatpakRemoteState) state = NULL; GPtrArray *matched_refs; - state = flatpak_dir_get_remote_state (self, remote, cancellable, error); + state = flatpak_dir_get_remote_state_optional (self, remote, cancellable, error); if (state == NULL) return NULL; @@ -8761,15 +8993,10 @@ g_autoptr(FlatpakRemoteState) state = NULL; g_autoptr(GError) my_error = NULL; - /* Atm this has to be optional, because otherwise we fail test-unsigned-summaries.sh due - * to the install failing with a wrong-gpg error, rather than silently ignoring this */ state = flatpak_dir_get_remote_state_optional (self, remote, cancellable, error); if (state == NULL) return NULL; - if (!flatpak_remote_state_ensure_summary (state, error)) - return NULL; - if (!flatpak_dir_remote_list_refs (self, state, &remote_refs, cancellable, error)) return NULL; @@ -8889,7 +9116,7 @@ g_autoptr(GHashTable) local_refs = NULL; int i; - if (!flatpak_dir_ensure_repo (self, NULL, error)) + if (!flatpak_dir_maybe_ensure_repo (self, NULL, error)) return NULL; local_refs = g_hash_table_new_full (flatpak_collection_ref_hash, @@ -9052,7 +9279,6 @@ /** * flatpak_dir_cleanup_undeployed_refs: - * * @self: a #FlatpakDir * @cancellable: (nullable) (optional): a #GCancellable * @error: a #GError @@ -9378,7 +9604,11 @@ prio_a = flatpak_dir_get_remote_prio (self, a_name); prio_b = flatpak_dir_get_remote_prio (self, b_name); - return prio_b - prio_a; + if (prio_b != prio_a) + return prio_b - prio_a; + + /* Ensure we have a well-defined order for same prio */ + return strcmp (a_name, b_name); } static gboolean @@ -9560,13 +9790,13 @@ g_bytes_get_size (data), 0, &local_error)) { - flatpak_fail (error, "Invalid .flatpakref: %s\n", local_error->message); + flatpak_fail (error, "Invalid .flatpakref: %s", local_error->message); return NULL; } if (!g_key_file_has_group (keyfile, source_group)) { - flatpak_fail (error, "Invalid .flatpakref\n"); + flatpak_fail (error, "Invalid .flatpakref"); return NULL; } @@ -9574,7 +9804,7 @@ FLATPAK_REPO_URL_KEY, NULL); if (uri == NULL) { - flatpak_fail (error, "Invalid .flatpakref\n"); + flatpak_fail (error, "Invalid .flatpakref"); return NULL; } @@ -9606,7 +9836,7 @@ decoded = g_base64_decode (gpg_key, &decoded_len); if (decoded_len < 10) /* Check some minimal size so we don't get crap */ { - flatpak_fail (error, "Invalid gpg key\n"); + flatpak_fail (error, "Invalid gpg key"); return NULL; } @@ -9939,6 +10169,38 @@ return (char **)g_ptr_array_free (g_steal_pointer (&found), FALSE); } +char ** +flatpak_dir_search_for_local_dependency (FlatpakDir *self, + const char *runtime_ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GPtrArray) found = g_ptr_array_new_with_free_func (g_free); + g_auto(GStrv) remotes = NULL; + int i; + + remotes = flatpak_dir_list_enumerated_remotes (self, cancellable, error); + if (remotes == NULL) + return NULL; + + for (i = 0; remotes != NULL && remotes[i] != NULL; i++) + { + const char *remote = remotes[i]; + g_autofree char *commit = NULL; + + if (flatpak_dir_get_remote_nodeps (self, remote)) + continue; + + commit = flatpak_dir_read_latest (self, remote, runtime_ref, NULL, NULL, NULL); + if (commit != NULL) + g_ptr_array_add (found, g_strdup (remote)); + } + + g_ptr_array_add (found, NULL); + + return (char **)g_ptr_array_free (g_steal_pointer (&found), FALSE); +} + gboolean flatpak_dir_remove_remote (FlatpakDir *self, gboolean force_remove, @@ -10061,6 +10323,8 @@ return flatpak_fail (error, "No configuration for remote %s specified", remote_name); + if (!flatpak_dir_check_add_remotes_config_dir (self, error)) + return FALSE; if (flatpak_dir_use_system_helper (self, NULL)) { @@ -10642,9 +10906,16 @@ state = flatpak_dir_get_remote_state (self, remote_name, cancellable, error); if (state == NULL) return NULL; - latest_commit = flatpak_remote_state_lookup_ref (state, ref, NULL, error); + + flatpak_remote_state_lookup_ref (state, ref, &latest_commit, NULL, error); if (latest_commit == NULL) - return NULL; + { + if (error != NULL && *error == NULL) + flatpak_fail (error, "Couldn't find latest checksum for ref %s in remote %s", + ref, state->remote_name); + return NULL; + } + opt_commit = latest_commit; } @@ -10702,6 +10973,7 @@ const char *checksum, gboolean no_autodownload, const char *download_if, + const char *autoprune_unless, gboolean autodelete, gboolean locale_subset) { @@ -10712,6 +10984,7 @@ FlatpakRelated *rel; gboolean download; gboolean delete = autodelete; + gboolean auto_prune = FALSE; g_auto(GStrv) ref_parts = g_strsplit (extension_ref, "/", -1); g_autoptr(GFile) unmaintained_path = NULL; @@ -10726,6 +10999,9 @@ flatpak_extension_matches_reason (ref_parts[1], download_if, !no_autodownload) || deploy_data != NULL; + if (!flatpak_extension_matches_reason (ref_parts[1], autoprune_unless, TRUE)) + auto_prune = TRUE; + /* Don't download if there is an unmaintained extension already installed */ unmaintained_path = flatpak_find_unmaintained_extension_dir_if_exists (ref_parts[1], @@ -10769,6 +11045,7 @@ rel->subpaths = g_steal_pointer (&subpaths); rel->download = download; rel->delete = delete; + rel->auto_prune = auto_prune; g_ptr_array_add (related, rel); } @@ -10818,28 +11095,41 @@ g_autofree char *extension = NULL; g_autofree char *version = g_key_file_get_string (metakey, groups[i], FLATPAK_METADATA_KEY_VERSION, NULL); + g_auto(GStrv) versions = g_key_file_get_string_list (metakey, groups[i], + FLATPAK_METADATA_KEY_VERSIONS, + NULL, NULL); gboolean subdirectories = g_key_file_get_boolean (metakey, groups[i], FLATPAK_METADATA_KEY_SUBDIRECTORIES, NULL); gboolean no_autodownload = g_key_file_get_boolean (metakey, groups[i], FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD, NULL); g_autofree char *download_if = g_key_file_get_string (metakey, groups[i], FLATPAK_METADATA_KEY_DOWNLOAD_IF, NULL); + g_autofree char *autoprune_unless = g_key_file_get_string (metakey, groups[i], + FLATPAK_METADATA_KEY_AUTOPRUNE_UNLESS, NULL); gboolean autodelete = g_key_file_get_boolean (metakey, groups[i], FLATPAK_METADATA_KEY_AUTODELETE, NULL); gboolean locale_subset = g_key_file_get_boolean (metakey, groups[i], FLATPAK_METADATA_KEY_LOCALE_SUBSET, NULL); g_autofree char *extension_collection_id = NULL; - const char *branch; + const char *default_branches[] = { NULL, NULL}; + const char **branches; g_autofree char *extension_ref = NULL; g_autofree char *checksum = NULL; + int branch_i; /* Parse actual extension name */ flatpak_parse_extension_with_tag (tagged_extension, &extension, NULL); - if (version) - branch = version; + if (versions) + branches = (const char **)versions; else - branch = parts[3]; + { + if (version) + default_branches[0] = version; + else + default_branches[0] = parts[3]; + branches = default_branches; + } #ifdef FLATPAK_ENABLE_P2P extension_collection_id = g_key_file_get_string (metakey, groups[i], @@ -10860,24 +11150,29 @@ g_clear_pointer (&extension_collection_id, g_free); extension_collection_id = g_strdup (state->collection_id); - extension_ref = g_build_filename ("runtime", extension, parts[2], branch, NULL); - - checksum = flatpak_remote_state_lookup_ref (state, extension_ref, NULL, NULL); - if (checksum) - { - add_related (self, related, extension, extension_collection_id, extension_ref, checksum, - no_autodownload, download_if, autodelete, locale_subset); - } - else if (subdirectories) + for (branch_i = 0; branches[branch_i] != NULL; branch_i++) { - g_auto(GStrv) refs = flatpak_remote_state_match_subrefs (state, extension_ref); - int j; - for (j = 0; refs[j] != NULL; j++) + const char *branch = branches[branch_i]; + + extension_ref = g_build_filename ("runtime", extension, parts[2], branch, NULL); + + if (flatpak_remote_state_lookup_ref (state, extension_ref, &checksum, NULL, NULL)) { - g_autofree char *subref_checksum = flatpak_remote_state_lookup_ref (state, refs[j], NULL, NULL); - if (subref_checksum) - add_related (self, related, extension, extension_collection_id, refs[j], subref_checksum, - no_autodownload, download_if, autodelete, locale_subset); + add_related (self, related, extension, extension_collection_id, extension_ref, checksum, + no_autodownload, download_if, autoprune_unless, autodelete, locale_subset); + } + else if (subdirectories) + { + g_auto(GStrv) refs = flatpak_remote_state_match_subrefs (state, extension_ref); + int j; + for (j = 0; refs[j] != NULL; j++) + { + g_autofree char *subref_checksum = NULL; + + if (flatpak_remote_state_lookup_ref (state, refs[j], &subref_checksum, NULL, NULL)) + add_related (self, related, extension, extension_collection_id, refs[j], subref_checksum, + no_autodownload, download_if, autoprune_unless, autodelete, locale_subset); + } } } } @@ -10910,20 +11205,24 @@ g_hash_table_iter_init (&hash_iter, refs); while (g_hash_table_iter_next (&hash_iter, &key, NULL)) { - char *ref = key; - g_auto(GStrv) cur_parts = g_strsplit (ref, "/", -1); + const char *partial_ref_and_origin = key; + g_autofree char *partial_ref = NULL; + g_auto(GStrv) cur_parts = NULL; + + ostree_parse_refspec (partial_ref_and_origin, NULL, &partial_ref, NULL); + + cur_parts = g_strsplit (partial_ref, "/", -1); /* Must match type, arch, branch */ - if (strcmp (parts[0], cur_parts[0]) != 0 || - strcmp (parts[2], cur_parts[2]) != 0 || - strcmp (parts[3], cur_parts[3]) != 0) + if (strcmp (parts[2], cur_parts[1]) != 0 || + strcmp (parts[3], cur_parts[2]) != 0) continue; /* But only prefix of id */ - if (!g_str_has_prefix (cur_parts[1], parts_prefix)) + if (!g_str_has_prefix (cur_parts[0], parts_prefix)) continue; - g_ptr_array_add (matches, g_strdup (ref)); + g_ptr_array_add (matches, g_strconcat (parts[0], "/", partial_ref, NULL)); } } @@ -10934,13 +11233,13 @@ flatpak_dir_find_local_related (FlatpakDir *self, const char *ref, const char *remote_name, + gboolean deployed, GCancellable *cancellable, GError **error) { g_autoptr(GFile) deploy_dir = NULL; g_autoptr(GFile) metadata = NULL; g_autofree char *metadata_contents = NULL; - gsize metadata_size; g_autoptr(GKeyFile) metakey = g_key_file_new (); int i; g_auto(GStrv) parts = NULL; @@ -10959,19 +11258,37 @@ if (!flatpak_dir_ensure_repo (self, cancellable, error)) return NULL; - deploy_dir = flatpak_dir_get_if_deployed (self, ref, NULL, cancellable); - if (deploy_dir == NULL) + if (deployed) { - g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, - _("%s not installed"), ref); - return NULL; - } + deploy_dir = flatpak_dir_get_if_deployed (self, ref, NULL, cancellable); + if (deploy_dir == NULL) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + _("%s not installed"), ref); + return NULL; + } - metadata = g_file_get_child (deploy_dir, "metadata"); - if (!g_file_load_contents (metadata, cancellable, &metadata_contents, &metadata_size, NULL, NULL)) - return g_steal_pointer (&related); /* No metadata => no related, but no error */ + metadata = g_file_get_child (deploy_dir, "metadata"); + if (!g_file_load_contents (metadata, cancellable, &metadata_contents, NULL, NULL, NULL)) + { + g_debug ("No metadata in local deploy"); + /* No metadata => no related, but no error */ + } + } + else + { + g_autoptr(GVariant) commit_data = flatpak_dir_read_latest_commit (self, remote_name, ref, NULL, NULL); + if (commit_data) + { + g_autoptr(GVariant) commit_metadata = g_variant_get_child_value (commit_data, 0); + g_variant_lookup (commit_metadata, "xa.metadata", "s", &metadata_contents); + if (metadata_contents == NULL) + g_debug ("No xa.metadata in local commit"); + } + } - if (g_key_file_load_from_data (metakey, metadata_contents, metadata_size, 0, NULL)) + if (metadata_contents && + g_key_file_load_from_data (metakey, metadata_contents, -1, 0, NULL)) { g_auto(GStrv) groups = NULL; @@ -10992,6 +11309,8 @@ FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD, NULL); g_autofree char *download_if = g_key_file_get_string (metakey, groups[i], FLATPAK_METADATA_KEY_DOWNLOAD_IF, NULL); + g_autofree char *autoprune_unless = g_key_file_get_string (metakey, groups[i], + FLATPAK_METADATA_KEY_AUTOPRUNE_UNLESS, NULL); gboolean autodelete = g_key_file_get_boolean (metakey, groups[i], FLATPAK_METADATA_KEY_AUTODELETE, NULL); gboolean locale_subset = g_key_file_get_boolean (metakey, groups[i], @@ -11039,7 +11358,7 @@ NULL)) { add_related (self, related, extension, extension_collection_id, extension_ref, - checksum, no_autodownload, download_if, autodelete, locale_subset); + checksum, no_autodownload, download_if, autoprune_unless, autodelete, locale_subset); } else if (subdirectories) { @@ -11061,7 +11380,7 @@ { add_related (self, related, extension, extension_collection_id, match, match_checksum, - no_autodownload, download_if, autodelete, locale_subset); + no_autodownload, download_if, autoprune_unless, autodelete, locale_subset); } } } diff -Nru flatpak-0.11.7/common/flatpak-dir.h flatpak-0.11.8.3/common/flatpak-dir.h --- flatpak-0.11.7/common/flatpak-dir.h 2018-05-03 07:22:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-dir.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,721 +0,0 @@ -/* - * Copyright © 2014 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_DIR_H__ -#define __FLATPAK_DIR_H__ - -#include - -#include "libglnx/libglnx.h" -#include -#include - -#define FLATPAK_TYPE_DIR flatpak_dir_get_type () -#define FLATPAK_DIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DIR, FlatpakDir)) -#define FLATPAK_IS_DIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DIR)) - -#define FLATPAK_TYPE_DEPLOY flatpak_deploy_get_type () -#define FLATPAK_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DEPLOY, FlatpakDeploy)) -#define FLATPAK_IS_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DEPLOY)) - -GType flatpak_dir_get_type (void); -GType flatpak_deploy_get_type (void); - -#define FLATPAK_REF_GROUP "Flatpak Ref" -#define FLATPAK_REF_VERSION_KEY "Version" -#define FLATPAK_REF_URL_KEY "Url" -#define FLATPAK_REF_RUNTIME_REPO_KEY "RuntimeRepo" -#define FLATPAK_REF_SUGGEST_REMOTE_NAME_KEY "SuggestRemoteName" -#define FLATPAK_REF_TITLE_KEY "Title" -#define FLATPAK_REF_GPGKEY_KEY "GPGKey" -#define FLATPAK_REF_IS_RUNTIME_KEY "IsRuntime" -#define FLATPAK_REF_NAME_KEY "Name" -#define FLATPAK_REF_BRANCH_KEY "Branch" - -#ifdef FLATPAK_ENABLE_P2P -#define FLATPAK_REF_COLLECTION_ID_KEY "CollectionID" -#endif /* FLATPAK_ENABLE_P2P */ - -#define FLATPAK_REPO_GROUP "Flatpak Repo" -#define FLATPAK_REPO_VERSION_KEY "Version" -#define FLATPAK_REPO_URL_KEY "Url" -#define FLATPAK_REPO_TITLE_KEY "Title" -#define FLATPAK_REPO_DEFAULT_BRANCH_KEY "DefaultBranch" -#define FLATPAK_REPO_GPGKEY_KEY "GPGKey" -#define FLATPAK_REPO_NODEPS_KEY "NoDeps" - -#ifdef FLATPAK_ENABLE_P2P -#define FLATPAK_REPO_COLLECTION_ID_KEY "CollectionID" -#endif /* FLATPAK_ENABLE_P2P */ - -#define FLATPAK_DEFAULT_UPDATE_FREQUENCY 100 -#define FLATPAK_CLI_UPDATE_FREQUENCY 300 - -typedef struct -{ - char *collection_id; /* (nullable) */ - char *ref; - char *commit; - char **subpaths; - gboolean download; - gboolean delete; -} FlatpakRelated; - -void flatpak_related_free (FlatpakRelated *related); - - -/* The remote state represent the state of the remote at a particular - time, including the summary file and the metadata (which may be from - the summary or from a branch. We create this once per highlevel operation - to avoid looking up the summary multiple times, but also to avoid races - if it happened to change in the middle of the operation */ -typedef struct -{ - char *remote_name; - char *collection_id; - GVariant *summary; - GBytes *summary_sig_bytes; - GError *summary_fetch_error; - GVariant *metadata; - GError *metadata_fetch_error; -} FlatpakRemoteState; - -void flatpak_remote_state_free (FlatpakRemoteState *remote_state); -gboolean flatpak_remote_state_ensure_summary (FlatpakRemoteState *self, - GError **error); -gboolean flatpak_remote_state_ensure_metadata (FlatpakRemoteState *self, - GError **error); -char *flatpak_remote_state_lookup_ref (FlatpakRemoteState *self, - const char *ref, - GVariant **out_variant, - GError **error); -char **flatpak_remote_state_match_subrefs (FlatpakRemoteState *self, - const char *ref); -gboolean flatpak_remote_state_lookup_repo_metadata (FlatpakRemoteState *self, - const char *key, - const char *format_string, - ...); -gboolean flatpak_remote_state_lookup_cache (FlatpakRemoteState *self, - const char *ref, - guint64 *download_size, - guint64 *installed_size, - const char **metadata, - GError **error); -GVariant *flatpak_remote_state_lookup_sparse_cache (FlatpakRemoteState *self, - const char *ref, - GError **error); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDir, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDeploy, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRelated, flatpak_related_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemoteState, flatpak_remote_state_free) - -typedef struct -{ - char *collection_id; - char *ref_name; -} FlatpakCollectionRef; - -FlatpakCollectionRef * flatpak_collection_ref_new (const char *collection_id, - const char *ref_name); -void flatpak_collection_ref_free (FlatpakCollectionRef *ref); -guint flatpak_collection_ref_hash (gconstpointer ref); -gboolean flatpak_collection_ref_equal (gconstpointer ref1, - gconstpointer ref2); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakCollectionRef, flatpak_collection_ref_free) - -typedef enum { - FLATPAK_HELPER_DEPLOY_FLAGS_NONE = 0, - FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE = 1 << 0, - FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY = 1 << 1, - FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL = 1 << 2, - FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL = 1 << 3, -} FlatpakHelperDeployFlags; - -#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL|FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL) - -typedef enum { - FLATPAK_HELPER_UNINSTALL_FLAGS_NONE = 0, - FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF = 1 << 0, - FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE = 1 << 1, -} FlatpakHelperUninstallFlags; - -#define FLATPAK_HELPER_UNINSTALL_FLAGS_ALL (FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF | FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE) - -typedef enum { - FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_NONE = 0, - FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE = 1 << 0, -} FlatpakHelperConfigureRemoteFlags; - -#define FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE) - -typedef enum { - FLATPAK_HELPER_CONFIGURE_FLAGS_NONE = 0, - FLATPAK_HELPER_CONFIGURE_FLAGS_UNSET = 1 << 0, -} FlatpakHelperConfigureFlags; - -#define FLATPAK_HELPER_CONFIGURE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_FLAGS_UNSET) - -typedef enum { - FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_NONE = 0, -} FlatpakHelperUpdateRemoteFlags; - -#define FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL (0) - -typedef enum { - FLATPAK_PULL_FLAGS_NONE = 0, - FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA = 1 << 0, - FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA = 1 << 1, - FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE = 1 << 2, - FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS = 1 << 3, -} FlatpakPullFlags; - -typedef enum { - FLATPAK_DIR_STORAGE_TYPE_DEFAULT = 0, - FLATPAK_DIR_STORAGE_TYPE_HARD_DISK, - FLATPAK_DIR_STORAGE_TYPE_SDCARD, - FLATPAK_DIR_STORAGE_TYPE_MMC, - FLATPAK_DIR_STORAGE_TYPE_NETWORK, -} FlatpakDirStorageType; - -GQuark flatpak_dir_error_quark (void); - -#ifndef FLATPAK_ENABLE_P2P -/* Rather than putting #ifdefs around all the function arguments for result sets, - * define away OstreeRepoFinderResult if we’re compiling without P2P support. - * The surrounding code should always pass in NULL if P2P support is disabled. */ -typedef void OstreeRepoFinderResult; -typedef void** OstreeRepoFinderResultv; - -static inline void no_op (gpointer data) {} - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, no_op) -G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, no_op, NULL) -#endif /* !FLATPAK_ENABLE_P2P */ - -/** - * FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT: - * - * s - origin - * s - commit - * as - subpaths - * t - installed size - * a{sv} - Metadata - */ -#define FLATPAK_DEPLOY_DATA_GVARIANT_STRING "(ssasta{sv})" -#define FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT G_VARIANT_TYPE (FLATPAK_DEPLOY_DATA_GVARIANT_STRING) - -GPtrArray * flatpak_get_system_base_dir_locations (GCancellable *cancellable, - GError **error); -GFile * flatpak_get_system_default_base_dir_location (void); -GFile * flatpak_get_user_base_dir_location (void); - -GKeyFile * flatpak_load_override_keyfile (const char *app_id, - gboolean user, - GError **error); -FlatpakContext *flatpak_load_override_file (const char *app_id, - gboolean user, - GError **error); -gboolean flatpak_save_override_keyfile (GKeyFile *metakey, - const char *app_id, - gboolean user, - GError **error); - -const char * flatpak_deploy_data_get_origin (GVariant *deploy_data); -const char * flatpak_deploy_data_get_commit (GVariant *deploy_data); -const char ** flatpak_deploy_data_get_subpaths (GVariant *deploy_data); -guint64 flatpak_deploy_data_get_installed_size (GVariant *deploy_data); -const char * flatpak_deploy_data_get_alt_id (GVariant *deploy_data); -const char * flatpak_deploy_data_get_eol (GVariant *deploy_data); -const char * flatpak_deploy_data_get_eol_rebase (GVariant *deploy_data); - -GFile * flatpak_deploy_get_dir (FlatpakDeploy *deploy); -GVariant * flatpak_load_deploy_data (GFile *deploy_dir, - GCancellable *cancellable, - GError **error); -GVariant * flatpak_deploy_get_deploy_data (FlatpakDeploy *deploy, - GCancellable *cancellable, - GError **error); -GFile * flatpak_deploy_get_files (FlatpakDeploy *deploy); -FlatpakContext *flatpak_deploy_get_overrides (FlatpakDeploy *deploy); -GKeyFile * flatpak_deploy_get_metadata (FlatpakDeploy *deploy); - -FlatpakDir * flatpak_dir_new (GFile *basedir, - gboolean user); -FlatpakDir * flatpak_dir_clone (FlatpakDir *self); -FlatpakDir *flatpak_dir_get_user (void); -FlatpakDir *flatpak_dir_get_system_default (void); -GPtrArray *flatpak_dir_get_system_list (GCancellable *cancellable, - GError **error); -FlatpakDir *flatpak_dir_get_system_by_id (const char *id, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_is_user (FlatpakDir *self); -void flatpak_dir_set_no_system_helper (FlatpakDir *self, - gboolean no_system_helper); -GFile * flatpak_dir_get_path (FlatpakDir *self); -GFile * flatpak_dir_get_changed_path (FlatpakDir *self); -const char *flatpak_dir_get_id (FlatpakDir *self); -const char *flatpak_dir_get_display_name (FlatpakDir *self); -char * flatpak_dir_get_name (FlatpakDir *self); -gint flatpak_dir_get_priority (FlatpakDir *self); -FlatpakDirStorageType flatpak_dir_get_storage_type (FlatpakDir *self); -GFile * flatpak_dir_get_deploy_dir (FlatpakDir *self, - const char *ref); -char * flatpak_dir_get_deploy_subdir (FlatpakDir *self, - const char *checksum, - const char * const * subpaths); -GFile * flatpak_dir_get_unmaintained_extension_dir (FlatpakDir *self, - const char *name, - const char *arch, - const char *branch); -GVariant * flatpak_dir_get_deploy_data (FlatpakDir *dir, - const char *ref, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_get_origin (FlatpakDir *self, - const char *ref, - GCancellable *cancellable, - GError **error); -char ** flatpak_dir_get_subpaths (FlatpakDir *self, - const char *ref, - GCancellable *cancellable, - GError **error); -GFile * flatpak_dir_get_exports_dir (FlatpakDir *self); -GFile * flatpak_dir_get_removed_dir (FlatpakDir *self); -GFile * flatpak_dir_get_if_deployed (FlatpakDir *self, - const char *ref, - const char *checksum, - GCancellable *cancellable); -GFile * flatpak_dir_get_unmaintained_extension_dir_if_exists (FlatpakDir *self, - const char *name, - const char *arch, - const char *branch, - GCancellable *cancellable); - -char ** flatpak_dir_search_for_dependency (FlatpakDir *self, - const char *runtime_ref, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_find_remote_ref (FlatpakDir *self, - const char *remote, - const char *name, - const char *opt_branch, - const char *opt_default_branch, - const char *opt_arch, - FlatpakKinds kinds, - FlatpakKinds *out_kind, - GCancellable *cancellable, - GError **error); -char ** flatpak_dir_find_remote_refs (FlatpakDir *self, - const char *remote, - const char *name, - const char *opt_branch, - const char *opt_arch, - FlatpakKinds kinds, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_find_local_ref (FlatpakDir *self, - const char *remote, - const char *name, - const char *opt_branch, - const char *opt_default_branch, - const char *opt_arch, - FlatpakKinds kinds, - FlatpakKinds *out_kind, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_find_installed_ref (FlatpakDir *self, - const char *opt_name, - const char *opt_branch, - const char *opt_arch, - FlatpakKinds kinds, - FlatpakKinds *out_kind, - GError **error); -char ** flatpak_dir_find_installed_refs (FlatpakDir *self, - const char *opt_name, - const char *opt_branch, - const char *opt_arch, - FlatpakKinds kinds, - GError **error); -FlatpakDeploy *flatpak_dir_load_deployed (FlatpakDir *self, - const char *ref, - const char *checksum, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_load_override (FlatpakDir *dir, - const char *app_id, - gsize *length, - GError **error); -OstreeRepo *flatpak_dir_get_repo (FlatpakDir *self); -gboolean flatpak_dir_ensure_path (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_use_child_repo (FlatpakDir *self); -gboolean flatpak_dir_ensure_system_child_repo (FlatpakDir *self, - GError **error); -gboolean flatpak_dir_recreate_repo (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_ensure_repo (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_maybe_ensure_repo (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_get_config (FlatpakDir *self, - const char *key, - GError **error); -gboolean flatpak_dir_set_config (FlatpakDir *self, - const char *key, - const char *value, - GError **error); -gboolean flatpak_dir_mark_changed (FlatpakDir *self, - GError **error); -gboolean flatpak_dir_remove_appstream (FlatpakDir *self, - const char *remote, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_deploy_appstream (FlatpakDir *self, - const char *remote, - const char *arch, - gboolean *out_changed, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_update_appstream (FlatpakDir *self, - const char *remote, - const char *arch, - gboolean *out_changed, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_pull (FlatpakDir *self, - FlatpakRemoteState *state, - const char *ref, - const char *opt_rev, - const OstreeRepoFinderResult * const *results, - const char **subpaths, - OstreeRepo *repo, - FlatpakPullFlags flatpak_flags, - OstreeRepoPullFlags flags, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_pull_untrusted_local (FlatpakDir *self, - const char *src_path, - const char *remote_name, - const char *ref, - const char **subpaths, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_list_refs_for_name (FlatpakDir *self, - const char *kind, - const char *name, - char ***refs, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_list_refs (FlatpakDir *self, - const char *kind, - char ***refs, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_read_latest (FlatpakDir *self, - const char *remote, - const char *ref, - char **out_alt_id, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_read_active (FlatpakDir *self, - const char *ref, - GCancellable *cancellable); -gboolean flatpak_dir_set_active (FlatpakDir *self, - const char *ref, - const char *checksum, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_current_ref (FlatpakDir *self, - const char *name, - GCancellable *cancellable); -gboolean flatpak_dir_drop_current_ref (FlatpakDir *self, - const char *name, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_make_current_ref (FlatpakDir *self, - const char *ref, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_list_deployed (FlatpakDir *self, - const char *ref, - char ***deployed_checksums, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_lock (FlatpakDir *self, - GLnxLockFile *lockfile, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_repo_lock (FlatpakDir *self, - GLnxLockFile *lockfile, - gboolean exclusive, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_deploy (FlatpakDir *self, - const char *origin, - const char *ref, - const char *checksum_or_latest, - const char * const * subpaths, - GVariant *old_deploy_data, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_deploy_update (FlatpakDir *self, - const char *ref, - const char *checksum, - const char **opt_subpaths, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_deploy_install (FlatpakDir *self, - const char *ref, - const char *origin, - const char **subpaths, - gboolean reinstall, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_install (FlatpakDir *self, - gboolean no_pull, - gboolean no_deploy, - gboolean no_static_deltas, - gboolean reinstall, - FlatpakRemoteState *state, - const char *ref, - const char **subpaths, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -char *flatpak_dir_ensure_bundle_remote (FlatpakDir *self, - GFile *file, - GBytes *extra_gpg_data, - char **out_ref, - char **out_metadata, - gboolean *out_created_remote, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_install_bundle (FlatpakDir *self, - GFile *file, - const char *remote, - char **out_ref, - GCancellable *cancellable, - GError **error); -char * flatpak_dir_check_for_update (FlatpakDir *self, - FlatpakRemoteState *state, - const char *ref, - const char *checksum_or_latest, - const char **opt_subpaths, - gboolean no_pull, - OstreeRepoFinderResult ***out_results, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_update (FlatpakDir *self, - gboolean no_pull, - gboolean no_deploy, - gboolean no_static_deltas, - gboolean allow_downgrade, - FlatpakRemoteState *state, - const char *ref, - const char *checksum_or_latest, - const OstreeRepoFinderResult * const *results, - const char **opt_subpaths, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_uninstall (FlatpakDir *self, - const char *ref, - FlatpakHelperUninstallFlags flags, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_undeploy (FlatpakDir *self, - const char *ref, - const char *checksum, - gboolean is_update, - gboolean force_remove, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_undeploy_all (FlatpakDir *self, - const char *ref, - gboolean force_remove, - gboolean *was_deployed_out, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_remove_ref (FlatpakDir *self, - const char *remote_name, - const char *ref, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_update_exports (FlatpakDir *self, - const char *app, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_prune (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_cleanup_removed (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_cleanup_undeployed_refs (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_collect_deployed_refs (FlatpakDir *self, - const char *type, - const char *name_prefix, - const char *branch, - const char *arch, - GHashTable *hash, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_collect_unmaintained_refs (FlatpakDir *self, - const char *name_prefix, - const char *arch, - const char *branch, - GHashTable *hash, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_remote_has_deploys (FlatpakDir *self, - const char *remote); -char *flatpak_dir_create_origin_remote (FlatpakDir *self, - const char *url, - const char *id, - const char *title, - const char *main_ref, - GBytes *gpg_data, - const char *collection_id, - GCancellable *cancellable, - GError **error); -void flatpak_dir_prune_origin_remote (FlatpakDir *self, - const char *remote); -gboolean flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, - GBytes *data, - const char *default_arch, - char **remote_name_out, - char **collection_id_out, - char **ref_out, - GError **error); -gboolean flatpak_dir_create_suggested_remote_for_ref_file (FlatpakDir *self, - GBytes *data, - GError **error); -GKeyFile * flatpak_dir_parse_repofile (FlatpakDir *self, - const char *remote_name, - gboolean from_ref, - GBytes *data, - GBytes **gpg_data_out, - GCancellable *cancellable, - GError **error); - -char *flatpak_dir_find_remote_by_uri (FlatpakDir *self, - const char *uri, - const char *collection_id); -gboolean flatpak_dir_has_remote (FlatpakDir *self, - const char *remote_name); -char **flatpak_dir_list_remotes (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -char **flatpak_dir_list_enumerated_remotes (FlatpakDir *self, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_modify_remote (FlatpakDir *self, - const char *remote_name, - GKeyFile *config, - GBytes *gpg_data, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_remove_remote (FlatpakDir *self, - gboolean force_remove, - const char *remote_name, - GCancellable *cancellable, - GError **error); -char *flatpak_dir_get_remote_title (FlatpakDir *self, - const char *remote_name); -char *flatpak_dir_get_remote_collection_id (FlatpakDir *self, - const char *remote_name); -char *flatpak_dir_get_remote_main_ref (FlatpakDir *self, - const char *remote_name); -gboolean flatpak_dir_get_remote_oci (FlatpakDir *self, - const char *remote_name); -char *flatpak_dir_get_remote_default_branch (FlatpakDir *self, - const char *remote_name); -int flatpak_dir_get_remote_prio (FlatpakDir *self, - const char *remote_name); -gboolean flatpak_dir_get_remote_noenumerate (FlatpakDir *self, - const char *remote_name); -gboolean flatpak_dir_get_remote_nodeps (FlatpakDir *self, - const char *remote_name); -gboolean flatpak_dir_get_remote_disabled (FlatpakDir *self, - const char *remote_name); -gboolean flatpak_dir_list_remote_refs (FlatpakDir *self, - FlatpakRemoteState *state, - GHashTable **refs, - GCancellable *cancellable, - GError **error); -GVariant * flatpak_dir_fetch_remote_commit (FlatpakDir *self, - const char *remote_name, - const char *ref, - const char *opt_commit, - char **out_commit, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_update_remote_configuration (FlatpakDir *self, - const char *remote, - GCancellable *cancellable, - GError **error); -gboolean flatpak_dir_update_remote_configuration_for_state (FlatpakDir *self, - FlatpakRemoteState *remote_state, - gboolean dry_run, - gboolean *has_changed_out, - GCancellable *cancellable, - GError **error); -FlatpakRemoteState * flatpak_dir_get_remote_state (FlatpakDir *self, - const char *remote, - GCancellable *cancellable, - GError **error); -FlatpakRemoteState * flatpak_dir_get_remote_state_for_summary (FlatpakDir *self, - const char *remote, - GBytes *opt_summary, - GBytes *opt_summary_sig, - GCancellable *cancellable, - GError **error); -FlatpakRemoteState * flatpak_dir_get_remote_state_optional (FlatpakDir *self, - const char *remote, - GCancellable *cancellable, - GError **error); -GPtrArray * flatpak_dir_find_remote_related (FlatpakDir *dir, - FlatpakRemoteState *state, - const char *ref, - GCancellable *cancellable, - GError **error); -GPtrArray * flatpak_dir_find_local_related (FlatpakDir *self, - const char *remote_name, - const char *ref, - GCancellable *cancellable, - GError **error); - -char ** flatpak_dir_get_default_locale_languages (FlatpakDir *self); -char ** flatpak_dir_get_locale_languages (FlatpakDir *self); -char ** flatpak_dir_get_locale_subpaths (FlatpakDir *self); - -#endif /* __FLATPAK_DIR_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-dir-private.h flatpak-0.11.8.3/common/flatpak-dir-private.h --- flatpak-0.11.7/common/flatpak-dir-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-dir-private.h 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,741 @@ +/* + * Copyright © 2014 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_DIR_H__ +#define __FLATPAK_DIR_H__ + +#include + +#include "libglnx/libglnx.h" +#include +#include + +#define FLATPAK_TYPE_DIR flatpak_dir_get_type () +#define FLATPAK_DIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DIR, FlatpakDir)) +#define FLATPAK_IS_DIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DIR)) + +#define FLATPAK_TYPE_DEPLOY flatpak_deploy_get_type () +#define FLATPAK_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DEPLOY, FlatpakDeploy)) +#define FLATPAK_IS_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DEPLOY)) + +GType flatpak_dir_get_type (void); +GType flatpak_deploy_get_type (void); + +#define FLATPAK_REF_GROUP "Flatpak Ref" +#define FLATPAK_REF_VERSION_KEY "Version" +#define FLATPAK_REF_URL_KEY "Url" +#define FLATPAK_REF_RUNTIME_REPO_KEY "RuntimeRepo" +#define FLATPAK_REF_SUGGEST_REMOTE_NAME_KEY "SuggestRemoteName" +#define FLATPAK_REF_TITLE_KEY "Title" +#define FLATPAK_REF_GPGKEY_KEY "GPGKey" +#define FLATPAK_REF_IS_RUNTIME_KEY "IsRuntime" +#define FLATPAK_REF_NAME_KEY "Name" +#define FLATPAK_REF_BRANCH_KEY "Branch" + +#ifdef FLATPAK_ENABLE_P2P +#define FLATPAK_REF_COLLECTION_ID_KEY "CollectionID" +#endif /* FLATPAK_ENABLE_P2P */ + +#define FLATPAK_REPO_GROUP "Flatpak Repo" +#define FLATPAK_REPO_VERSION_KEY "Version" +#define FLATPAK_REPO_URL_KEY "Url" +#define FLATPAK_REPO_TITLE_KEY "Title" +#define FLATPAK_REPO_DEFAULT_BRANCH_KEY "DefaultBranch" +#define FLATPAK_REPO_GPGKEY_KEY "GPGKey" +#define FLATPAK_REPO_NODEPS_KEY "NoDeps" + +#ifdef FLATPAK_ENABLE_P2P +#define FLATPAK_REPO_COLLECTION_ID_KEY "CollectionID" +#endif /* FLATPAK_ENABLE_P2P */ + +#define FLATPAK_DEFAULT_UPDATE_FREQUENCY 100 +#define FLATPAK_CLI_UPDATE_FREQUENCY 300 + +typedef struct +{ + char *collection_id; /* (nullable) */ + char *ref; + char *commit; + char **subpaths; + gboolean download; + gboolean delete; + gboolean auto_prune; +} FlatpakRelated; + +void flatpak_related_free (FlatpakRelated *related); + + +/* The remote state represent the state of the remote at a particular + time, including the summary file and the metadata (which may be from + the summary or from a branch. We create this once per highlevel operation + to avoid looking up the summary multiple times, but also to avoid races + if it happened to change in the middle of the operation */ +typedef struct +{ + char *remote_name; + char *collection_id; + GVariant *summary; + GBytes *summary_sig_bytes; + GError *summary_fetch_error; + GVariant *metadata; + GError *metadata_fetch_error; +} FlatpakRemoteState; + +void flatpak_remote_state_free (FlatpakRemoteState *remote_state); +gboolean flatpak_remote_state_ensure_summary (FlatpakRemoteState *self, + GError **error); +gboolean flatpak_remote_state_ensure_metadata (FlatpakRemoteState *self, + GError **error); +gboolean flatpak_remote_state_lookup_ref (FlatpakRemoteState *self, + const char *ref, + char **out_checksum, + GVariant **out_variant, + GError **error); +char **flatpak_remote_state_match_subrefs (FlatpakRemoteState *self, + const char *ref); +gboolean flatpak_remote_state_lookup_repo_metadata (FlatpakRemoteState *self, + const char *key, + const char *format_string, + ...); +gboolean flatpak_remote_state_lookup_cache (FlatpakRemoteState *self, + const char *ref, + guint64 *download_size, + guint64 *installed_size, + const char **metadata, + GError **error); +GVariant *flatpak_remote_state_lookup_sparse_cache (FlatpakRemoteState *self, + const char *ref, + GError **error); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDir, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDeploy, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRelated, flatpak_related_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemoteState, flatpak_remote_state_free) + +typedef struct +{ + char *collection_id; + char *ref_name; +} FlatpakCollectionRef; + +FlatpakCollectionRef * flatpak_collection_ref_new (const char *collection_id, + const char *ref_name); +void flatpak_collection_ref_free (FlatpakCollectionRef *ref); +guint flatpak_collection_ref_hash (gconstpointer ref); +gboolean flatpak_collection_ref_equal (gconstpointer ref1, + gconstpointer ref2); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakCollectionRef, flatpak_collection_ref_free) + +typedef enum { + FLATPAK_HELPER_DEPLOY_FLAGS_NONE = 0, + FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE = 1 << 0, + FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY = 1 << 1, + FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL = 1 << 2, + FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL = 1 << 3, +} FlatpakHelperDeployFlags; + +#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL|FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL) + +typedef enum { + FLATPAK_HELPER_UNINSTALL_FLAGS_NONE = 0, + FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF = 1 << 0, + FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE = 1 << 1, +} FlatpakHelperUninstallFlags; + +#define FLATPAK_HELPER_UNINSTALL_FLAGS_ALL (FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF | FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE) + +typedef enum { + FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_NONE = 0, + FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE = 1 << 0, +} FlatpakHelperConfigureRemoteFlags; + +#define FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE) + +typedef enum { + FLATPAK_HELPER_CONFIGURE_FLAGS_NONE = 0, + FLATPAK_HELPER_CONFIGURE_FLAGS_UNSET = 1 << 0, +} FlatpakHelperConfigureFlags; + +#define FLATPAK_HELPER_CONFIGURE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_FLAGS_UNSET) + +typedef enum { + FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_NONE = 0, +} FlatpakHelperUpdateRemoteFlags; + +#define FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL (0) + +typedef enum { + FLATPAK_PULL_FLAGS_NONE = 0, + FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA = 1 << 0, + FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA = 1 << 1, + FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE = 1 << 2, + FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS = 1 << 3, +} FlatpakPullFlags; + +typedef enum { + FLATPAK_DIR_STORAGE_TYPE_DEFAULT = 0, + FLATPAK_DIR_STORAGE_TYPE_HARD_DISK, + FLATPAK_DIR_STORAGE_TYPE_SDCARD, + FLATPAK_DIR_STORAGE_TYPE_MMC, + FLATPAK_DIR_STORAGE_TYPE_NETWORK, +} FlatpakDirStorageType; + +GQuark flatpak_dir_error_quark (void); + +#ifndef FLATPAK_ENABLE_P2P +/* Rather than putting #ifdefs around all the function arguments for result sets, + * define away OstreeRepoFinderResult if we’re compiling without P2P support. + * The surrounding code should always pass in NULL if P2P support is disabled. */ +typedef void OstreeRepoFinderResult; +typedef void** OstreeRepoFinderResultv; + +static inline void no_op (gpointer data) {} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, no_op) +G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, no_op, NULL) +#endif /* !FLATPAK_ENABLE_P2P */ + +/** + * FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT: + * + * s - origin + * s - commit + * as - subpaths + * t - installed size + * a{sv} - Metadata + */ +#define FLATPAK_DEPLOY_DATA_GVARIANT_STRING "(ssasta{sv})" +#define FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT G_VARIANT_TYPE (FLATPAK_DEPLOY_DATA_GVARIANT_STRING) + +GPtrArray * flatpak_get_system_base_dir_locations (GCancellable *cancellable, + GError **error); +GFile * flatpak_get_system_default_base_dir_location (void); +GFile * flatpak_get_user_base_dir_location (void); + +GKeyFile * flatpak_load_override_keyfile (const char *app_id, + gboolean user, + GError **error); +FlatpakContext *flatpak_load_override_file (const char *app_id, + gboolean user, + GError **error); +gboolean flatpak_save_override_keyfile (GKeyFile *metakey, + const char *app_id, + gboolean user, + GError **error); + +const char * flatpak_deploy_data_get_origin (GVariant *deploy_data); +const char * flatpak_deploy_data_get_commit (GVariant *deploy_data); +const char ** flatpak_deploy_data_get_subpaths (GVariant *deploy_data); +guint64 flatpak_deploy_data_get_installed_size (GVariant *deploy_data); +const char * flatpak_deploy_data_get_alt_id (GVariant *deploy_data); +const char * flatpak_deploy_data_get_eol (GVariant *deploy_data); +const char * flatpak_deploy_data_get_eol_rebase (GVariant *deploy_data); +const char * flatpak_deploy_data_get_runtime (GVariant *deploy_data); + +GFile * flatpak_deploy_get_dir (FlatpakDeploy *deploy); +GVariant * flatpak_load_deploy_data (GFile *deploy_dir, + GCancellable *cancellable, + GError **error); +GVariant * flatpak_deploy_get_deploy_data (FlatpakDeploy *deploy, + GCancellable *cancellable, + GError **error); +GFile * flatpak_deploy_get_files (FlatpakDeploy *deploy); +FlatpakContext *flatpak_deploy_get_overrides (FlatpakDeploy *deploy); +GKeyFile * flatpak_deploy_get_metadata (FlatpakDeploy *deploy); + +FlatpakDir * flatpak_dir_new (GFile *basedir, + gboolean user); +FlatpakDir * flatpak_dir_clone (FlatpakDir *self); +FlatpakDir *flatpak_dir_get_user (void); +FlatpakDir *flatpak_dir_get_system_default (void); +GPtrArray *flatpak_dir_get_system_list (GCancellable *cancellable, + GError **error); +FlatpakDir *flatpak_dir_get_system_by_id (const char *id, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_is_user (FlatpakDir *self); +void flatpak_dir_set_no_system_helper (FlatpakDir *self, + gboolean no_system_helper); +GFile * flatpak_dir_get_path (FlatpakDir *self); +GFile * flatpak_dir_get_changed_path (FlatpakDir *self); +const char *flatpak_dir_get_id (FlatpakDir *self); +const char *flatpak_dir_get_display_name (FlatpakDir *self); +char * flatpak_dir_get_name (FlatpakDir *self); +gint flatpak_dir_get_priority (FlatpakDir *self); +FlatpakDirStorageType flatpak_dir_get_storage_type (FlatpakDir *self); +GFile * flatpak_dir_get_deploy_dir (FlatpakDir *self, + const char *ref); +char * flatpak_dir_get_deploy_subdir (FlatpakDir *self, + const char *checksum, + const char * const * subpaths); +GFile * flatpak_dir_get_unmaintained_extension_dir (FlatpakDir *self, + const char *name, + const char *arch, + const char *branch); +GVariant * flatpak_dir_get_deploy_data (FlatpakDir *dir, + const char *ref, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_get_origin (FlatpakDir *self, + const char *ref, + GCancellable *cancellable, + GError **error); +char ** flatpak_dir_get_subpaths (FlatpakDir *self, + const char *ref, + GCancellable *cancellable, + GError **error); +GFile * flatpak_dir_get_exports_dir (FlatpakDir *self); +GFile * flatpak_dir_get_removed_dir (FlatpakDir *self); +GFile * flatpak_dir_get_if_deployed (FlatpakDir *self, + const char *ref, + const char *checksum, + GCancellable *cancellable); +GFile * flatpak_dir_get_unmaintained_extension_dir_if_exists (FlatpakDir *self, + const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable); + +char ** flatpak_dir_search_for_local_dependency (FlatpakDir *self, + const char *runtime_ref, + GCancellable *cancellable, + GError **error); +char ** flatpak_dir_search_for_dependency (FlatpakDir *self, + const char *runtime_ref, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_find_remote_ref (FlatpakDir *self, + const char *remote, + const char *name, + const char *opt_branch, + const char *opt_default_branch, + const char *opt_arch, + FlatpakKinds kinds, + FlatpakKinds *out_kind, + GCancellable *cancellable, + GError **error); +char ** flatpak_dir_find_remote_refs (FlatpakDir *self, + const char *remote, + const char *name, + const char *opt_branch, + const char *opt_arch, + FlatpakKinds kinds, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_find_local_ref (FlatpakDir *self, + const char *remote, + const char *name, + const char *opt_branch, + const char *opt_default_branch, + const char *opt_arch, + FlatpakKinds kinds, + FlatpakKinds *out_kind, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_find_installed_ref (FlatpakDir *self, + const char *opt_name, + const char *opt_branch, + const char *opt_arch, + FlatpakKinds kinds, + FlatpakKinds *out_kind, + GError **error); +char ** flatpak_dir_find_installed_refs (FlatpakDir *self, + const char *opt_name, + const char *opt_branch, + const char *opt_arch, + FlatpakKinds kinds, + GError **error); +FlatpakDeploy *flatpak_dir_load_deployed (FlatpakDir *self, + const char *ref, + const char *checksum, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_load_override (FlatpakDir *dir, + const char *app_id, + gsize *length, + GError **error); +OstreeRepo *flatpak_dir_get_repo (FlatpakDir *self); +gboolean flatpak_dir_ensure_path (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_use_child_repo (FlatpakDir *self); +gboolean flatpak_dir_ensure_system_child_repo (FlatpakDir *self, + GError **error); +gboolean flatpak_dir_recreate_repo (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_ensure_repo (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_maybe_ensure_repo (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_get_config (FlatpakDir *self, + const char *key, + GError **error); +gboolean flatpak_dir_set_config (FlatpakDir *self, + const char *key, + const char *value, + GError **error); +gboolean flatpak_dir_mark_changed (FlatpakDir *self, + GError **error); +gboolean flatpak_dir_remove_appstream (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_deploy_appstream (FlatpakDir *self, + const char *remote, + const char *arch, + gboolean *out_changed, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_update_appstream (FlatpakDir *self, + const char *remote, + const char *arch, + gboolean *out_changed, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_pull (FlatpakDir *self, + FlatpakRemoteState *state, + const char *ref, + const char *opt_rev, + const OstreeRepoFinderResult * const *results, + const char **subpaths, + OstreeRepo *repo, + FlatpakPullFlags flatpak_flags, + OstreeRepoPullFlags flags, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_pull_untrusted_local (FlatpakDir *self, + const char *src_path, + const char *remote_name, + const char *ref, + const char **subpaths, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_list_refs_for_name (FlatpakDir *self, + const char *kind, + const char *name, + char ***refs, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_list_refs (FlatpakDir *self, + const char *kind, + char ***refs, + GCancellable *cancellable, + GError **error); +GVariant * flatpak_dir_read_latest_commit (FlatpakDir *self, + const char *remote, + const char *ref, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_read_latest (FlatpakDir *self, + const char *remote, + const char *ref, + char **out_alt_id, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_read_active (FlatpakDir *self, + const char *ref, + GCancellable *cancellable); +gboolean flatpak_dir_set_active (FlatpakDir *self, + const char *ref, + const char *checksum, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_current_ref (FlatpakDir *self, + const char *name, + GCancellable *cancellable); +gboolean flatpak_dir_drop_current_ref (FlatpakDir *self, + const char *name, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_make_current_ref (FlatpakDir *self, + const char *ref, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_list_deployed (FlatpakDir *self, + const char *ref, + char ***deployed_checksums, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_lock (FlatpakDir *self, + GLnxLockFile *lockfile, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_repo_lock (FlatpakDir *self, + GLnxLockFile *lockfile, + gboolean exclusive, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_deploy (FlatpakDir *self, + const char *origin, + const char *ref, + const char *checksum_or_latest, + const char * const * subpaths, + GVariant *old_deploy_data, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_deploy_update (FlatpakDir *self, + const char *ref, + const char *checksum, + const char **opt_subpaths, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_deploy_install (FlatpakDir *self, + const char *ref, + const char *origin, + const char **subpaths, + gboolean reinstall, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_install (FlatpakDir *self, + gboolean no_pull, + gboolean no_deploy, + gboolean no_static_deltas, + gboolean reinstall, + FlatpakRemoteState *state, + const char *ref, + const char **subpaths, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error); +char *flatpak_dir_ensure_bundle_remote (FlatpakDir *self, + GFile *file, + GBytes *extra_gpg_data, + char **out_ref, + char **out_metadata, + gboolean *out_created_remote, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_install_bundle (FlatpakDir *self, + GFile *file, + const char *remote, + char **out_ref, + GCancellable *cancellable, + GError **error); +char * flatpak_dir_check_for_update (FlatpakDir *self, + FlatpakRemoteState *state, + const char *ref, + const char *checksum_or_latest, + const char **opt_subpaths, + gboolean no_pull, + OstreeRepoFinderResult ***out_results, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_update (FlatpakDir *self, + gboolean no_pull, + gboolean no_deploy, + gboolean no_static_deltas, + gboolean allow_downgrade, + FlatpakRemoteState *state, + const char *ref, + const char *checksum_or_latest, + const OstreeRepoFinderResult * const *results, + const char **opt_subpaths, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_uninstall (FlatpakDir *self, + const char *ref, + FlatpakHelperUninstallFlags flags, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_undeploy (FlatpakDir *self, + const char *ref, + const char *checksum, + gboolean is_update, + gboolean force_remove, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_undeploy_all (FlatpakDir *self, + const char *ref, + gboolean force_remove, + gboolean *was_deployed_out, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_remove_ref (FlatpakDir *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_update_exports (FlatpakDir *self, + const char *app, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_prune (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_run_triggers (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_cleanup_removed (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_cleanup_undeployed_refs (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_collect_deployed_refs (FlatpakDir *self, + const char *type, + const char *name_prefix, + const char *branch, + const char *arch, + GHashTable *hash, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_collect_unmaintained_refs (FlatpakDir *self, + const char *name_prefix, + const char *arch, + const char *branch, + GHashTable *hash, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_remote_has_deploys (FlatpakDir *self, + const char *remote); +char *flatpak_dir_create_origin_remote (FlatpakDir *self, + const char *url, + const char *id, + const char *title, + const char *main_ref, + GBytes *gpg_data, + const char *collection_id, + GCancellable *cancellable, + GError **error); +void flatpak_dir_prune_origin_remote (FlatpakDir *self, + const char *remote); +gboolean flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, + GBytes *data, + const char *default_arch, + char **remote_name_out, + char **collection_id_out, + char **ref_out, + GError **error); +gboolean flatpak_dir_create_suggested_remote_for_ref_file (FlatpakDir *self, + GBytes *data, + GError **error); +GKeyFile * flatpak_dir_parse_repofile (FlatpakDir *self, + const char *remote_name, + gboolean from_ref, + GBytes *data, + GBytes **gpg_data_out, + GCancellable *cancellable, + GError **error); + +char *flatpak_dir_find_remote_by_uri (FlatpakDir *self, + const char *uri, + const char *collection_id); +gboolean flatpak_dir_has_remote (FlatpakDir *self, + const char *remote_name); +char **flatpak_dir_list_remotes (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +char **flatpak_dir_list_enumerated_remotes (FlatpakDir *self, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_modify_remote (FlatpakDir *self, + const char *remote_name, + GKeyFile *config, + GBytes *gpg_data, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_remove_remote (FlatpakDir *self, + gboolean force_remove, + const char *remote_name, + GCancellable *cancellable, + GError **error); +char *flatpak_dir_get_remote_title (FlatpakDir *self, + const char *remote_name); +char *flatpak_dir_get_remote_collection_id (FlatpakDir *self, + const char *remote_name); +char *flatpak_dir_get_remote_main_ref (FlatpakDir *self, + const char *remote_name); +gboolean flatpak_dir_get_remote_oci (FlatpakDir *self, + const char *remote_name); +char *flatpak_dir_get_remote_default_branch (FlatpakDir *self, + const char *remote_name); +int flatpak_dir_get_remote_prio (FlatpakDir *self, + const char *remote_name); +gboolean flatpak_dir_get_remote_noenumerate (FlatpakDir *self, + const char *remote_name); +gboolean flatpak_dir_get_remote_nodeps (FlatpakDir *self, + const char *remote_name); +gboolean flatpak_dir_get_remote_disabled (FlatpakDir *self, + const char *remote_name); +gboolean flatpak_dir_list_remote_refs (FlatpakDir *self, + FlatpakRemoteState *state, + GHashTable **refs, + GCancellable *cancellable, + GError **error); +GVariant * flatpak_dir_fetch_remote_commit (FlatpakDir *self, + const char *remote_name, + const char *ref, + const char *opt_commit, + char **out_commit, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_update_remote_configuration (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error); +gboolean flatpak_dir_update_remote_configuration_for_state (FlatpakDir *self, + FlatpakRemoteState *remote_state, + gboolean dry_run, + gboolean *has_changed_out, + GCancellable *cancellable, + GError **error); +FlatpakRemoteState * flatpak_dir_get_remote_state (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error); +FlatpakRemoteState * flatpak_dir_get_remote_state_for_summary (FlatpakDir *self, + const char *remote, + GBytes *opt_summary, + GBytes *opt_summary_sig, + GCancellable *cancellable, + GError **error); +FlatpakRemoteState * flatpak_dir_get_remote_state_optional (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error); +FlatpakRemoteState * flatpak_dir_get_remote_state_local_only (FlatpakDir *self, + const char *remote, + GCancellable *cancellable, + GError **error); +GPtrArray * flatpak_dir_find_remote_related (FlatpakDir *dir, + FlatpakRemoteState *state, + const char *ref, + GCancellable *cancellable, + GError **error); +GPtrArray * flatpak_dir_find_local_related (FlatpakDir *self, + const char *remote_name, + const char *ref, + gboolean deployed, + GCancellable *cancellable, + GError **error); + +char ** flatpak_dir_get_default_locale_languages (FlatpakDir *self); +char ** flatpak_dir_get_locale_languages (FlatpakDir *self); +char ** flatpak_dir_get_locale_subpaths (FlatpakDir *self); + +#endif /* __FLATPAK_DIR_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-enum-types.c.template flatpak-0.11.8.3/common/flatpak-enum-types.c.template --- flatpak-0.11.7/common/flatpak-enum-types.c.template 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-enum-types.c.template 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,40 @@ +/*** BEGIN file-header ***/ +#include "config.h" +#include +#include +#include +#include + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ diff -Nru flatpak-0.11.7/common/flatpak-enum-types.h.template flatpak-0.11.8.3/common/flatpak-enum-types.h.template --- flatpak-0.11.7/common/flatpak-enum-types.h.template 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-enum-types.h.template 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef __FLATPAK_ENUM_TYPES_H__ +#define __FLATPAK_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +FLATPAK_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __GIO_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff -Nru flatpak-0.11.7/common/flatpak-error.c flatpak-0.11.8.3/common/flatpak-error.c --- flatpak-0.11.7/common/flatpak-error.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-error.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,34 @@ +/* flatpak-error.c + * + * Copyright (C) 2015 Red Hat, Inc + * + * This file 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 of the + * License, or (at your option) any later version. + * + * This file 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 program. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-error.h" + +#include + +/** + * SECTION:flatpak-error + * @Title: Error codes + * + */ + +/* This is actually defined in common/flatpak-utils.c so the common code can report errors */ diff -Nru flatpak-0.11.7/common/flatpak-error.h flatpak-0.11.8.3/common/flatpak-error.h --- flatpak-0.11.7/common/flatpak-error.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-error.h 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,62 @@ +/* flatpak-error.c + * + * Copyright (C) 2015 Red Hat, Inc + * + * This file 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 of the + * License, or (at your option) any later version. + * + * This file 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 program. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#ifndef FLATPAK_ERROR_H +#define FLATPAK_ERROR_H + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/** + * FlatpakError: + * @FLATPAK_ERROR_ALREADY_INSTALLED: App/runtime is already installed + * @FLATPAK_ERROR_NOT_INSTALLED: App/runtime is not installed + * @FLATPAK_ERROR_ONLY_PULLED: App/runtime was only pulled into the local + * repository but not installed. + * @FLATPAK_ERROR_DIFFERENT_REMOTE: The App/Runtime is already installed, but from a different remote. + * @FLATPAK_ERROR_ABORTED: The transaction was aborted (returned TRUE in operation-error signal). + * @FLATPAK_ERROR_SKIPPED: The App/Runtime install was skipped due to earlier errors. + * @FLATPAK_ERROR_NEED_NEW_FLATPAK: The App/Runtime needs a more recent version of flatpak. + * + * Error codes for library functions. + */ +typedef enum { + FLATPAK_ERROR_ALREADY_INSTALLED, + FLATPAK_ERROR_NOT_INSTALLED, + FLATPAK_ERROR_ONLY_PULLED, + FLATPAK_ERROR_DIFFERENT_REMOTE, + FLATPAK_ERROR_ABORTED, + FLATPAK_ERROR_SKIPPED, + FLATPAK_ERROR_NEED_NEW_FLATPAK, +} FlatpakError; + +#define FLATPAK_ERROR flatpak_error_quark () + +FLATPAK_EXTERN GQuark flatpak_error_quark (void); + +G_END_DECLS + +#endif /* FLATPAK_ERROR_H */ diff -Nru flatpak-0.11.7/common/flatpak-exports.c flatpak-0.11.8.3/common/flatpak-exports.c --- flatpak-0.11.7/common/flatpak-exports.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-exports.c 2018-05-30 13:58:57.000000000 +0100 @@ -27,7 +27,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -37,13 +40,13 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-exports.h" -#include "flatpak-run.h" +#include "flatpak-exports-private.h" +#include "flatpak-run-private.h" #include "flatpak-proxy.h" -#include "flatpak-utils.h" -#include "flatpak-dir.h" -#include "flatpak-systemd-dbus.h" -#include "lib/flatpak-error.h" +#include "flatpak-utils-private.h" +#include "flatpak-dir-private.h" +#include "flatpak-systemd-dbus-generated.h" +#include "flatpak-error.h" /* We don't want to export paths pointing into these, because they are readonly (so we can't create mountpoints there) and don't match whats on the host anyway */ @@ -400,6 +403,75 @@ g_hash_table_replace (exports->hash, ep->path, ep); } +/* AUTOFS mounts are tricky, as using them as a source in a bind mount + * causes the mount to trigger, which can take a long time (or forever) + * waiting for a device or network mount. We try to open the directory + * but time out after a while, ignoring the mount. Unfortunately we + * have to mess with forks and stuff to be able to handle the timeout. + */ +static gboolean +check_if_autofs_works (const char *path) +{ + int selfpipe[2]; + struct timeval timeout; + pid_t pid; + fd_set rfds; + int res; + int wstatus; + + if (pipe2 (selfpipe, O_CLOEXEC) == -1) + return FALSE; + + fcntl (selfpipe[0], F_SETFL, fcntl (selfpipe[0], F_GETFL) | O_NONBLOCK); + fcntl (selfpipe[1], F_SETFL, fcntl (selfpipe[1], F_GETFL) | O_NONBLOCK); + + pid = fork(); + if (pid == -1) + { + close (selfpipe[0]); + close (selfpipe[1]); + return FALSE; + } + + if (pid == 0) + { + /* Note: open, close and _exit are signal-async-safe, so it is ok to call in the child after fork */ + + close (selfpipe[0]); /* Close unused read end */ + int dir_fd = open (path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY); + _exit (dir_fd == -1 ? 1 : 0); + } + + /* Parent */ + close (selfpipe[1]); /* Close unused write end */ + + /* 200 msec timeout*/ + timeout.tv_sec = 0; + timeout.tv_usec = 200 * 1000; + + FD_ZERO (&rfds); + FD_SET (selfpipe[0], &rfds); + res = select (selfpipe[0]+1, &rfds, NULL, NULL, &timeout); + + close (selfpipe[0]); + + if (res == -1 /* Error */ || res == 0) /* Timeout */ + { + /* Kill, but then waitpid to avoid zombie */ + kill (pid, SIGKILL); + } + + if (waitpid (pid, &wstatus, 0) != pid) + return FALSE; + + if (res == -1 /* Error */ || res == 0) /* Timeout */ + return FALSE; + + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) + return FALSE; + + return TRUE; +} /* We use level to avoid infinite recursion */ static gboolean @@ -410,8 +482,10 @@ { g_autofree char *canonical = NULL; struct stat st; + struct statfs stfs; char *slash; int i; + glnx_autofd int o_path_fd = -1; if (level > 40) /* 40 is the current kernel ELOOP check */ { @@ -426,7 +500,11 @@ } /* Check if it exists at all */ - if (lstat (path, &st) != 0) + o_path_fd = open (path, O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (o_path_fd == -1) + return FALSE; + + if (fstat (o_path_fd, &st) != 0) return FALSE; /* Don't expose weird things */ @@ -436,6 +514,19 @@ S_ISSOCK (st.st_mode))) return FALSE; + /* O_PATH + fstatfs is the magic that we need to statfs without automounting the target */ + if (fstatfs (o_path_fd, &stfs) != 0) + return FALSE; + + if (stfs.f_type == AUTOFS_SUPER_MAGIC) + { + if (!check_if_autofs_works (path)) + { + g_debug ("ignoring blocking autofs path %s", path); + return FALSE; + } + } + path = canonical = flatpak_canonicalize_filename (path); for (i = 0; dont_export_in[i] != NULL; i++) diff -Nru flatpak-0.11.7/common/flatpak-exports.h flatpak-0.11.8.3/common/flatpak-exports.h --- flatpak-0.11.7/common/flatpak-exports.h 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-exports.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,61 +0,0 @@ -/* - * Copyright © 2014-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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_EXPORTS_H__ -#define __FLATPAK_EXPORTS_H__ - -#include "libglnx/libglnx.h" -#include "flatpak-bwrap.h" - -/* In numerical order of more privs */ -typedef enum { - FLATPAK_FILESYSTEM_MODE_READ_ONLY = 1, - FLATPAK_FILESYSTEM_MODE_READ_WRITE = 2, - FLATPAK_FILESYSTEM_MODE_CREATE = 3, -} FlatpakFilesystemMode; - -typedef struct _FlatpakExports FlatpakExports; - -void flatpak_exports_free (FlatpakExports *exports); -FlatpakExports *flatpak_exports_new (void); -void flatpak_exports_append_bwrap_args (FlatpakExports *exports, - FlatpakBwrap *bwrap); -void flatpak_exports_add_home_expose (FlatpakExports *exports, - FlatpakFilesystemMode mode); -void flatpak_exports_add_path_expose (FlatpakExports *exports, - FlatpakFilesystemMode mode, - const char *path); -void flatpak_exports_add_path_tmpfs (FlatpakExports *exports, - const char *path); -void flatpak_exports_add_path_expose_or_hide (FlatpakExports *exports, - FlatpakFilesystemMode mode, - const char *path); -void flatpak_exports_add_path_dir (FlatpakExports *exports, - const char *path); - -gboolean flatpak_exports_path_is_visible (FlatpakExports *exports, - const char *path); -FlatpakFilesystemMode flatpak_exports_path_get_mode (FlatpakExports *exports, - const char *path); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakExports, flatpak_exports_free); - - -#endif /* __FLATPAK_EXPORTS_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-exports-private.h flatpak-0.11.8.3/common/flatpak-exports-private.h --- flatpak-0.11.7/common/flatpak-exports-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-exports-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,61 @@ +/* + * Copyright © 2014-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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_EXPORTS_H__ +#define __FLATPAK_EXPORTS_H__ + +#include "libglnx/libglnx.h" +#include "flatpak-bwrap-private.h" + +/* In numerical order of more privs */ +typedef enum { + FLATPAK_FILESYSTEM_MODE_READ_ONLY = 1, + FLATPAK_FILESYSTEM_MODE_READ_WRITE = 2, + FLATPAK_FILESYSTEM_MODE_CREATE = 3, +} FlatpakFilesystemMode; + +typedef struct _FlatpakExports FlatpakExports; + +void flatpak_exports_free (FlatpakExports *exports); +FlatpakExports *flatpak_exports_new (void); +void flatpak_exports_append_bwrap_args (FlatpakExports *exports, + FlatpakBwrap *bwrap); +void flatpak_exports_add_home_expose (FlatpakExports *exports, + FlatpakFilesystemMode mode); +void flatpak_exports_add_path_expose (FlatpakExports *exports, + FlatpakFilesystemMode mode, + const char *path); +void flatpak_exports_add_path_tmpfs (FlatpakExports *exports, + const char *path); +void flatpak_exports_add_path_expose_or_hide (FlatpakExports *exports, + FlatpakFilesystemMode mode, + const char *path); +void flatpak_exports_add_path_dir (FlatpakExports *exports, + const char *path); + +gboolean flatpak_exports_path_is_visible (FlatpakExports *exports, + const char *path); +FlatpakFilesystemMode flatpak_exports_path_get_mode (FlatpakExports *exports, + const char *path); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakExports, flatpak_exports_free); + + +#endif /* __FLATPAK_EXPORTS_H__ */ diff -Nru flatpak-0.11.7/common/flatpak.h flatpak-0.11.8.3/common/flatpak.h --- flatpak-0.11.7/common/flatpak.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_H__ +#define __FLATPAK_H__ + +#define __FLATPAK_H_INSIDE__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef __FLATPAK_H_INSIDE__ + +#endif /* __FLATPAK_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-installation.c flatpak-0.11.8.3/common/flatpak-installation.c --- flatpak-0.11.7/common/flatpak-installation.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installation.c 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,2661 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include + +#ifdef FLATPAK_ENABLE_P2P +#include +#include +#endif /* FLATPAK_ENABLE_P2P */ + +#include "flatpak-installation-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-installation.h" +#include "flatpak-installed-ref-private.h" +#include "flatpak-transaction-private.h" +#include "flatpak-related-ref-private.h" +#include "flatpak-remote-private.h" +#include "flatpak-remote-ref-private.h" +#include "flatpak-enum-types.h" +#include "flatpak-dir-private.h" +#include "flatpak-run-private.h" +#include "flatpak-error.h" + +/** + * SECTION:flatpak-installation + * @Title: FlatpakInstallation + * @Short_description: Installation information + * + * FlatpakInstallation is the toplevel object that software installers + * should use to operate on an flatpak applications. + * + * An FlatpakInstallation object provides information about an installation + * location for flatpak applications. Typical installation locations are either + * system-wide (in $prefix/var/lib/flatpak) or per-user (in ~/.local/share/flatpak). + * + * FlatpakInstallation can list configured remotes as well as installed application + * and runtime references (in short: refs). It can also run, install, update and + * uninstall applications and runtimes, using #FlatpakTransaction. + */ + +typedef struct _FlatpakInstallationPrivate FlatpakInstallationPrivate; + +G_LOCK_DEFINE_STATIC (dir); + +struct _FlatpakInstallationPrivate +{ + /* All raw access to this should be protected by the dir lock. The FlatpakDir object is mostly + threadsafe (apart from pull transactions being a singleton on it), however we replace it during + flatpak_installation_drop_caches(), so every user needs to keep its own reference alive until + done. */ + FlatpakDir *dir_unlocked; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakInstallation, flatpak_installation, G_TYPE_OBJECT) + +enum { + PROP_0, +}; + +static void +no_progress_cb (OstreeAsyncProgress *progress, gpointer user_data) +{ +} + +static void +flatpak_installation_finalize (GObject *object) +{ + FlatpakInstallation *self = FLATPAK_INSTALLATION (object); + FlatpakInstallationPrivate *priv = flatpak_installation_get_instance_private (self); + + g_object_unref (priv->dir_unlocked); + + G_OBJECT_CLASS (flatpak_installation_parent_class)->finalize (object); +} + +static void +flatpak_installation_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_installation_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_installation_class_init (FlatpakInstallationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_installation_get_property; + object_class->set_property = flatpak_installation_set_property; + object_class->finalize = flatpak_installation_finalize; + +} + +static void +flatpak_installation_init (FlatpakInstallation *self) +{ +} + +static FlatpakInstallation * +flatpak_installation_new_steal_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error) +{ + FlatpakInstallation *self; + FlatpakInstallationPrivate *priv; + + if (!flatpak_dir_maybe_ensure_repo (dir, NULL, error)) + { + g_object_unref (dir); + return NULL; + } + + self = g_object_new (FLATPAK_TYPE_INSTALLATION, NULL); + priv = flatpak_installation_get_instance_private (self); + + priv->dir_unlocked = dir; + + return self; +} + +FlatpakInstallation * +flatpak_installation_new_for_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_new_steal_dir (g_object_ref (dir), + cancellable, + error); +} + +/** + * flatpak_get_default_arch: + * + * Returns the canonical name for the arch of the current machine. + * + * Returns: an arch string + */ +const char * +flatpak_get_default_arch (void) +{ + return flatpak_get_arch (); +} + +/** + * flatpak_get_supported_arches: + * + * Returns the canonical names for the arches that are supported (i.e. can run) + * on the current machine, in order of priority (default is first). + * + * Returns: a zero terminated array of arch strings + */ +const char * const * +flatpak_get_supported_arches (void) +{ + return (const char * const *)flatpak_get_arches (); +} + +/** + * flatpak_get_system_installations: + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists the system installations according to the current configuration and current + * availability (e.g. doesn't return a configured installation if not reachable). + * + * Returns: (transfer container) (element-type FlatpakInstallation): a GPtrArray of + * #FlatpakInstallation instances + * + * Since: 0.8 + */ +GPtrArray * +flatpak_get_system_installations (GCancellable *cancellable, + GError **error) +{ + g_autoptr(GPtrArray) system_dirs = NULL; + g_autoptr(GPtrArray) installs = NULL; + GPtrArray *ret = NULL; + int i; + + system_dirs = flatpak_dir_get_system_list (cancellable, error); + if (system_dirs == NULL) + goto out; + + installs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + for (i = 0; i < system_dirs->len; i++) + { + g_autoptr(GError) local_error = NULL; + FlatpakDir *install_dir = g_ptr_array_index (system_dirs, i); + g_autoptr(FlatpakInstallation) installation = NULL; + + installation = flatpak_installation_new_for_dir (install_dir, + cancellable, + &local_error); + if (installation != NULL) + g_ptr_array_add (installs, g_steal_pointer (&installation)); + else + { + /* Warn about the problem and continue without listing this installation. */ + g_autofree char *dir_name = flatpak_dir_get_name (install_dir); + g_warning ("Unable to create FlatpakInstallation for %s: %s", + dir_name, local_error->message); + } + } + + if (installs->len == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "No system installations found"); + } + + ret = g_steal_pointer (&installs); + + out: + return ret; +} + +/** + * flatpak_installation_new_system: + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakInstallation for the system-wide installation. + * + * Returns: (transfer full): a new #FlatpakInstallation + */ +FlatpakInstallation * +flatpak_installation_new_system (GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_new_steal_dir (flatpak_dir_get_system_default (), cancellable, error); +} + +/** + * flatpak_installation_new_system_with_id: + * @id: (nullable): the ID of the system-wide installation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakInstallation for the system-wide installation @id. + * + * Returns: (transfer full): a new #FlatpakInstallation + * + * Since: 0.8 + */ +FlatpakInstallation * +flatpak_installation_new_system_with_id (const char *id, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) install_dir = NULL; + g_autoptr(FlatpakInstallation) installation = NULL; + g_autoptr(GError) local_error = NULL; + + install_dir = flatpak_dir_get_system_by_id (id, cancellable, error); + if (install_dir == NULL) + return NULL; + + installation = flatpak_installation_new_for_dir (install_dir, + cancellable, + &local_error); + if (installation == NULL) + { + g_debug ("Error creating Flatpak installation: %s", local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + } + + g_debug ("Found Flatpak installation for '%s'", id); + return g_steal_pointer (&installation); +} + +/** + * flatpak_installation_new_user: + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakInstallation for the per-user installation. + * + * Returns: (transfer full): a new #FlatpakInstallation + */ +FlatpakInstallation * +flatpak_installation_new_user (GCancellable *cancellable, + GError **error) +{ + flatpak_migrate_from_xdg_app (); + + return flatpak_installation_new_steal_dir (flatpak_dir_get_user (), cancellable, error); +} + +/** + * flatpak_installation_new_for_path: + * @path: a #GFile + * @user: whether this is a user-specific location + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakInstallation for the installation at the given @path. + * + * Returns: (transfer full): a new #FlatpakInstallation + */ +FlatpakInstallation * +flatpak_installation_new_for_path (GFile *path, gboolean user, + GCancellable *cancellable, + GError **error) +{ + flatpak_migrate_from_xdg_app (); + + return flatpak_installation_new_steal_dir (flatpak_dir_new (path, user), cancellable, error); +} + +static FlatpakDir * +_flatpak_installation_get_dir (FlatpakInstallation *self, gboolean ensure_repo, GError **error) +{ + FlatpakInstallationPrivate *priv = flatpak_installation_get_instance_private (self); + FlatpakDir *dir; + + G_LOCK (dir); + + if (ensure_repo && flatpak_dir_get_repo (priv->dir_unlocked) == NULL) + { + if (!flatpak_dir_ensure_repo (priv->dir_unlocked, NULL, error)) + { + dir = NULL; + goto out; + } + } + + dir = g_object_ref (priv->dir_unlocked); + +out: + G_UNLOCK (dir); + return dir; +} + +static FlatpakDir * +flatpak_installation_get_dir (FlatpakInstallation *self, GError **error) +{ + return _flatpak_installation_get_dir (self, TRUE, error); +} + +static FlatpakDir * +flatpak_installation_get_dir_maybe_no_repo (FlatpakInstallation *self) +{ + return _flatpak_installation_get_dir (self, FALSE, NULL); +} + +FlatpakDir * +flatpak_installation_clone_dir (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + return g_steal_pointer (&dir_clone); +} + +/** + * flatpak_installation_drop_caches: + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Drops all internal (in-memory) caches. For instance, this may be needed to pick up new or changed + * remotes configured outside this installation instance. + * + * Returns: %TRUE on success, %FALSE on error + */ +gboolean +flatpak_installation_drop_caches (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + FlatpakInstallationPrivate *priv = flatpak_installation_get_instance_private (self); + FlatpakDir *clone, *old; + gboolean res = FALSE; + + G_LOCK (dir); + + old = priv->dir_unlocked; + clone = flatpak_dir_clone (priv->dir_unlocked); + + if (flatpak_dir_maybe_ensure_repo (clone, cancellable, error)) + { + priv->dir_unlocked = clone; + g_object_unref (old); + res = TRUE; + } + + G_UNLOCK (dir); + + return res; +} + +/** + * flatpak_installation_get_is_user: + * @self: a #FlatpakInstallation + * + * Returns whether the installation is for a user-specific location. + * + * Returns: %TRUE if @self is a per-user installation + */ +gboolean +flatpak_installation_get_is_user (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + return flatpak_dir_is_user (dir); +} + +/** + * flatpak_installation_get_path: + * @self: a #FlatpakInstallation + * + * Returns the installation location for @self. + * + * Returns: (transfer full): an #GFile + */ +GFile * +flatpak_installation_get_path (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + return g_object_ref (flatpak_dir_get_path (dir)); +} + +/** + * flatpak_installation_get_id: + * @self: a #FlatpakInstallation + * + * Returns the ID of the system installation for @self. + * + * Returns: (transfer none): a string with the installation's ID + * + * Since: 0.8 + */ +const char * +flatpak_installation_get_id (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + return flatpak_dir_get_id (dir); +} + +/** + * flatpak_installation_get_display_name: + * @self: a #FlatpakInstallation + * + * Returns the display name of the system installation for @self. + * + * Returns: (transfer none): a string with the installation's display name + * + * Since: 0.8 + */ +const char * +flatpak_installation_get_display_name (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + return flatpak_dir_get_display_name (dir); +} + +/** + * flatpak_installation_get_priority: + * @self: a #FlatpakInstallation + * + * Returns the numeric priority of the system installation for @self. + * + * Returns: an integer with the configured priority value + * + * Since: 0.8 + */ +gint +flatpak_installation_get_priority (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + return flatpak_dir_get_priority (dir); +} + +/** + * flatpak_installation_get_storage_type: + * @self: a #FlatpakInstallation + * + * Returns the type of storage of the system installation for @self. + * + * Returns: a #FlatpakStorageType + * + * Since: 0.8 + */FlatpakStorageType +flatpak_installation_get_storage_type (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + + switch (flatpak_dir_get_storage_type (dir)) + { + case FLATPAK_DIR_STORAGE_TYPE_HARD_DISK: + return FLATPAK_STORAGE_TYPE_HARD_DISK; + + case FLATPAK_DIR_STORAGE_TYPE_SDCARD: + return FLATPAK_STORAGE_TYPE_SDCARD; + + case FLATPAK_DIR_STORAGE_TYPE_MMC: + return FLATPAK_STORAGE_TYPE_MMC; + + case FLATPAK_DIR_STORAGE_TYPE_NETWORK: + return FLATPAK_STORAGE_TYPE_NETWORK; + + default: + return FLATPAK_STORAGE_TYPE_DEFAULT; + } + + return FLATPAK_STORAGE_TYPE_DEFAULT; +} + +/** + * flatpak_installation_launch: + * @self: a #FlatpakInstallation + * @name: name of the app to launch + * @arch: (nullable): which architecture to launch (default: current architecture) + * @branch: (nullable): which branch of the application (default: "master") + * @commit: (nullable): the commit of @branch to launch + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Launch an installed application. + * + * You can use flatpak_installation_get_installed_ref() or + * flatpak_installation_get_current_installed_app() to find out what builds + * are available, in order to get a value for @commit. + * + * Returns: %TRUE, unless an error occurred + */ +gboolean +flatpak_installation_launch (FlatpakInstallation *self, + const char *name, + const char *arch, + const char *branch, + const char *commit, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDeploy) app_deploy = NULL; + g_autofree char *app_ref = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + app_ref = + flatpak_build_app_ref (name, branch, arch); + + app_deploy = + flatpak_dir_load_deployed (dir, app_ref, + commit, + cancellable, error); + if (app_deploy == NULL) + return FALSE; + + return flatpak_run_app (app_ref, + app_deploy, + NULL, NULL, + NULL, NULL, + FLATPAK_RUN_FLAG_BACKGROUND, + NULL, + NULL, 0, + cancellable, error); +} + + +static FlatpakInstalledRef * +get_ref (FlatpakDir *dir, + const char *full_ref, + GCancellable *cancellable, + GError **error) +{ + g_auto(GStrv) parts = NULL; + const char *origin = NULL; + const char *commit = NULL; + const char *alt_id = NULL; + g_autofree char *latest_alt_id = NULL; + g_autoptr(GFile) deploy_dir = NULL; + g_autoptr(GFile) deploy_subdir = NULL; + g_autofree char *deploy_path = NULL; + g_autofree char *latest_commit = NULL; + g_autofree char *deploy_subdirname = NULL; + g_autoptr(GVariant) deploy_data = NULL; + g_autofree const char **subpaths = NULL; + gboolean is_current = FALSE; + guint64 installed_size = 0; + + parts = g_strsplit (full_ref, "/", -1); + + deploy_data = flatpak_dir_get_deploy_data (dir, full_ref, cancellable, error); + if (deploy_data == NULL) + return NULL; + origin = flatpak_deploy_data_get_origin (deploy_data); + commit = flatpak_deploy_data_get_commit (deploy_data); + alt_id = flatpak_deploy_data_get_alt_id (deploy_data); + subpaths = flatpak_deploy_data_get_subpaths (deploy_data); + installed_size = flatpak_deploy_data_get_installed_size (deploy_data); + + deploy_dir = flatpak_dir_get_deploy_dir (dir, full_ref); + deploy_subdirname = flatpak_dir_get_deploy_subdir (dir, commit, subpaths); + deploy_subdir = g_file_get_child (deploy_dir, deploy_subdirname); + deploy_path = g_file_get_path (deploy_subdir); + + if (strcmp (parts[0], "app") == 0) + { + g_autofree char *current = + flatpak_dir_current_ref (dir, parts[1], cancellable); + if (current && strcmp (full_ref, current) == 0) + is_current = TRUE; + } + + latest_commit = flatpak_dir_read_latest (dir, origin, full_ref, &latest_alt_id, NULL, NULL); + + return flatpak_installed_ref_new (full_ref, + alt_id ? alt_id : commit, + latest_alt_id ? latest_alt_id : latest_commit, + origin, subpaths, + deploy_path, + installed_size, + is_current, + flatpak_deploy_data_get_eol (deploy_data), + flatpak_deploy_data_get_eol_rebase (deploy_data)); +} + +/** + * flatpak_installation_get_installed_ref: + * @self: a #FlatpakInstallation + * @kind: whether this is an app or runtime + * @name: name of the app/runtime to fetch + * @arch: (nullable): which architecture to fetch (default: current architecture) + * @branch: (nullable): which branch to fetch (default: "master") + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Returns information about an installed ref, such as the available builds, + * its size, location, etc. + * + * Returns: (transfer full): an #FlatpakInstalledRef, or %NULL if an error occurred + */ +FlatpakInstalledRef * +flatpak_installation_get_installed_ref (FlatpakInstallation *self, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GFile) deploy = NULL; + g_autofree char *ref = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + if (arch == NULL) + arch = flatpak_get_arch (); + + if (kind == FLATPAK_REF_KIND_APP) + ref = flatpak_build_app_ref (name, branch, arch); + else + ref = flatpak_build_runtime_ref (name, branch, arch); + + + deploy = flatpak_dir_get_if_deployed (dir, + ref, NULL, cancellable); + if (deploy == NULL) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + "Ref %s not installed", ref); + return NULL; + } + + return get_ref (dir, ref, cancellable, error); +} + +/** + * flatpak_installation_get_current_installed_app: + * @self: a #FlatpakInstallation + * @name: the name of the app + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Get the last build of reference @name that was installed with + * flatpak_installation_install(), or %NULL if the reference has + * never been installed locally. + * + * Returns: (transfer full): an #FlatpakInstalledRef + */ +FlatpakInstalledRef * +flatpak_installation_get_current_installed_app (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GFile) deploy = NULL; + g_autofree char *current = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + current = flatpak_dir_current_ref (dir, name, cancellable); + if (current) + deploy = flatpak_dir_get_if_deployed (dir, + current, NULL, cancellable); + + if (deploy == NULL) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + "App %s not installed", name); + return NULL; + } + + return get_ref (dir, current, cancellable, error); +} + +/** + * flatpak_installation_list_installed_refs: + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists the installed references. + * + * Returns: (transfer container) (element-type FlatpakInstalledRef): a GPtrArray of + * #FlatpakInstalledRef instances + */ +GPtrArray * +flatpak_installation_list_installed_refs (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_auto(GStrv) raw_refs_app = NULL; + g_auto(GStrv) raw_refs_runtime = NULL; + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_object_unref); + int i; + + if (!flatpak_dir_list_refs (dir, + "app", + &raw_refs_app, + cancellable, error)) + return NULL; + + for (i = 0; raw_refs_app[i] != NULL; i++) + { + g_autoptr(GError) local_error = NULL; + FlatpakInstalledRef *ref = get_ref (dir, raw_refs_app[i], cancellable, &local_error); + if (ref != NULL) + g_ptr_array_add (refs, ref); + else + g_warning ("Unexpected failure getting ref for %s: %s", raw_refs_app[i], local_error->message); + } + + if (!flatpak_dir_list_refs (dir, + "runtime", + &raw_refs_runtime, + cancellable, error)) + return NULL; + + for (i = 0; raw_refs_runtime[i] != NULL; i++) + { + g_autoptr(GError) local_error = NULL; + FlatpakInstalledRef *ref = get_ref (dir, raw_refs_runtime[i], cancellable, &local_error); + if (ref != NULL) + g_ptr_array_add (refs, ref); + else + g_warning ("Unexpected failure getting ref for %s: %s", raw_refs_runtime[i], local_error->message); + } + + return g_steal_pointer (&refs); +} + +/** + * flatpak_installation_list_installed_refs_by_kind: + * @self: a #FlatpakInstallation + * @kind: the kind of installation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists the installed references of a specific kind. + * + * Returns: (transfer container) (element-type FlatpakInstalledRef): a GPtrArray of + * #FlatpakInstalledRef instances + */ +GPtrArray * +flatpak_installation_list_installed_refs_by_kind (FlatpakInstallation *self, + FlatpakRefKind kind, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_auto(GStrv) raw_refs = NULL; + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_object_unref); + int i; + + if (!flatpak_dir_list_refs (dir, + kind == FLATPAK_REF_KIND_APP ? "app" : "runtime", + &raw_refs, + cancellable, error)) + return NULL; + + for (i = 0; raw_refs[i] != NULL; i++) + { + g_autoptr(GError) local_error = NULL; + FlatpakInstalledRef *ref = get_ref (dir, raw_refs[i], cancellable, &local_error); + if (ref != NULL) + g_ptr_array_add (refs, ref); + else + g_warning ("Unexpected failure getting ref for %s: %s", raw_refs[i], local_error->message); + } + + return g_steal_pointer (&refs); +} + +#ifdef FLATPAK_ENABLE_P2P +static void +async_result_cb (GObject *obj, + GAsyncResult *result, + gpointer user_data) +{ + GAsyncResult **result_out = user_data; + *result_out = g_object_ref (result); +} +#endif /* FLATPAK_ENABLE_P2P */ + +/** + * flatpak_installation_list_installed_refs_for_update: + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists the installed references that has a remote update that is not + * locally available. However, even though an app is not returned by this + * it can have local updates available that has not been deployed. Look + * at commit vs latest_commit on installed apps for this. + * + * Returns: (transfer container) (element-type FlatpakInstalledRef): a GPtrArray of + * #FlatpakInstalledRef instances, or %NULL on error + */ +GPtrArray * +flatpak_installation_list_installed_refs_for_update (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GPtrArray) updates = NULL; /* (element-type FlatpakInstalledRef) */ + g_autoptr(GPtrArray) installed = NULL; /* (element-type FlatpakInstalledRef) */ + g_autoptr(GPtrArray) remotes = NULL; /* (element-type FlatpakRemote) */ + g_autoptr(GHashTable) remote_commits = NULL; /* (element-type utf8 utf8) */ + int i, j; +#ifdef FLATPAK_ENABLE_P2P + g_autoptr(FlatpakDir) dir = NULL; + g_auto(OstreeRepoFinderResultv) results = NULL; + g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GPtrArray) collection_refs = NULL; /* (element-type OstreeCollectionRef) */ +#endif /* FLATPAK_ENABLE_P2P */ + + remote_commits = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + remotes = flatpak_installation_list_remotes (self, cancellable, error); + if (remotes == NULL) + return NULL; + + for (i = 0; i < remotes->len; i++) + { + FlatpakRemote *remote = g_ptr_array_index (remotes, i); + g_autoptr(GPtrArray) refs = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree char *collection_id = NULL; + const char *remote_name = flatpak_remote_get_name (remote); + + if (flatpak_remote_get_disabled (remote)) + continue; + + /* Remotes with collection IDs will be handled separately below */ + collection_id = flatpak_remote_get_collection_id (remote); + if (collection_id != NULL) + continue; + + /* We ignore errors here. we don't want one remote to fail us */ + refs = flatpak_installation_list_remote_refs_sync (self, + remote_name, + cancellable, &local_error); + if (refs != NULL) + { + for (j = 0; j < refs->len; j++) + { + FlatpakRemoteRef *remote_ref = g_ptr_array_index (refs, j); + g_autofree char *full_ref = flatpak_ref_format_ref (FLATPAK_REF (remote_ref)); + g_autofree char *key = g_strdup_printf ("%s:%s", remote_name, full_ref); + + g_hash_table_insert (remote_commits, g_steal_pointer (&key), + g_strdup (flatpak_ref_get_commit (FLATPAK_REF (remote_ref)))); + } + } + else + { + g_debug ("Update: Failed to read remote %s: %s", + flatpak_remote_get_name (remote), + local_error->message); + } + } + + installed = flatpak_installation_list_installed_refs (self, cancellable, error); + if (installed == NULL) + return NULL; + + updates = g_ptr_array_new_with_free_func (g_object_unref); + + for (i = 0; i < installed->len; i++) + { + FlatpakInstalledRef *installed_ref = g_ptr_array_index (installed, i); + const char *remote_name = flatpak_installed_ref_get_origin (installed_ref); + g_autofree char *full_ref = flatpak_ref_format_ref (FLATPAK_REF (installed_ref)); + g_autofree char *key = g_strdup_printf ("%s:%s", remote_name, full_ref); + const char *remote_commit = g_hash_table_lookup (remote_commits, key); + const char *local_commit = flatpak_installed_ref_get_latest_commit (installed_ref); + + if (remote_commit != NULL && + g_strcmp0 (remote_commit, local_commit) != 0) + g_ptr_array_add (updates, g_object_ref (installed_ref)); + } + +#ifdef FLATPAK_ENABLE_P2P + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + collection_refs = g_ptr_array_new (); + + for (i = 0; i < installed->len; i++) + { + FlatpakInstalledRef *installed_ref = g_ptr_array_index (installed, i); + g_autofree char *collection_id = NULL; + const char *remote_name = flatpak_installed_ref_get_origin (installed_ref); + + collection_id = flatpak_dir_get_remote_collection_id (dir, remote_name); + if (collection_id != NULL) + { + const char *ref = flatpak_ref_format_ref (FLATPAK_REF (installed_ref)); + OstreeCollectionRef *c_r = ostree_collection_ref_new (collection_id, ref); + g_ptr_array_add (collection_refs, c_r); + } + } + + /* if we do not have any collection refs, then we shouldn't try to find + * dynamic remotes for them, to avoid extra unnecessary processing, and also + * because the refs array cannot be empty in ostree_repo_find_remotes_async + * (otherwise it early returns and we never get our callback called) */ + if (collection_refs->len > 0) + { + g_autoptr(GMainContextPopDefault) context = NULL; + + g_ptr_array_add (collection_refs, NULL); + + context = flatpak_main_context_new_default (); + + ostree_repo_find_remotes_async (flatpak_dir_get_repo (dir), + (const OstreeCollectionRef * const *) collection_refs->pdata, + NULL, /* no options */ + NULL, /* default finders */ + NULL, /* no progress */ + cancellable, + async_result_cb, + &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + results = ostree_repo_find_remotes_finish (flatpak_dir_get_repo (dir), result, error); + + if (results == NULL) + return NULL; + } + + for (i = 0; i < installed->len; i++) + { + FlatpakInstalledRef *installed_ref = g_ptr_array_index (installed, i); + const char *remote_name = flatpak_installed_ref_get_origin (installed_ref); + const char *ref = flatpak_ref_format_ref (FLATPAK_REF (installed_ref)); + g_autofree char *collection_id = NULL; + g_autoptr(OstreeCollectionRef) collection_ref = NULL; + + collection_id = flatpak_dir_get_remote_collection_id (dir, remote_name); + collection_ref = ostree_collection_ref_new (collection_id, ref); + + /* Look for matching remote refs that are updates */ + for (j = 0; results != NULL && results[j] != NULL; j++) + { + const char *local_commit, *remote_commit; + + local_commit = flatpak_installed_ref_get_latest_commit (installed_ref); + remote_commit = g_hash_table_lookup (results[j]->ref_to_checksum, collection_ref); + if (remote_commit == NULL || g_strcmp0 (remote_commit, local_commit) == 0) + continue; + + /* The ref_to_checksum map only tells us if this remote is offering + * the latest commit of the available remotes, not what the timestamp + * is. So unless we're using a new enough version of ostree to + * provide ref_to_timestamp, we have no way of knowing if the commit + * is an update or a downgrade (we could check the summary but + * there's no signature, and we'd have to add the temporary remote to + * the local configuration). + */ +#ifdef OSTREE_VERSION_2018_5 + { + guint64 local_timestamp = 0; + guint64 *remote_timestamp; + g_autoptr(GVariant) commit_v = NULL; + + if (ostree_repo_load_commit (flatpak_dir_get_repo (dir), local_commit, &commit_v, NULL, NULL)) + local_timestamp = ostree_commit_get_timestamp (commit_v); + + remote_timestamp = g_hash_table_lookup (results[j]->ref_to_timestamp, collection_ref); + *remote_timestamp = GUINT64_FROM_BE (*remote_timestamp); + + g_debug ("%s: Comparing local timestamp %" G_GUINT64_FORMAT " to remote timestamp %" + G_GUINT64_FORMAT " on ref (%s, %s)", G_STRFUNC, local_timestamp, *remote_timestamp, + collection_ref->collection_id, collection_ref->ref_name); + + /* The timestamp could be 0 due to an error reading it. Assume + * it's an update until proven otherwise. */ + if (*remote_timestamp != 0 && *remote_timestamp <= local_timestamp) + continue; + } +#endif /* OSTREE_VERSION_2018_5 */ + + g_ptr_array_add (updates, g_object_ref (installed_ref)); + + /* Move on to the next ref so we don't add duplicates */ + break; + } + } +#endif /* FLATPAK_ENABLE_P2P */ + + return g_steal_pointer (&updates); +} + +/* Find all USB and LAN repositories which share the same collection ID as + * @remote_name, and add a #FlatpakRemote to @remotes for each of them. The caller + * must initialise @remotes. Returns %TRUE without modifying @remotes if the + * given remote doesn’t have a collection ID configured. + * + * FIXME: If this were async, the parallelisation could be handled in the caller. */ +static gboolean +list_remotes_for_configured_remote (FlatpakInstallation *self, + const gchar *remote_name, + FlatpakDir *dir, + gboolean types_filter[], + GPtrArray *remotes /* (element-type FlatpakRemote) */, + GCancellable *cancellable, + GError **error) +{ +#ifdef FLATPAK_ENABLE_P2P + g_autofree gchar *collection_id = NULL; + OstreeCollectionRef ref; + const OstreeCollectionRef *refs[2] = { NULL, }; + g_autofree gchar *appstream_ref = NULL; + g_auto(OstreeRepoFinderResultv) results = NULL; + g_autoptr(GAsyncResult) result = NULL; + g_autoptr(OstreeRepoFinder) finder_mount = NULL, finder_avahi = NULL; + OstreeRepoFinder *finders[3] = { NULL, }; + gsize i; + guint finder_index = 0; + g_autoptr(GMainContextPopDefault) context = NULL; + + if (!types_filter[FLATPAK_REMOTE_TYPE_USB] && + !types_filter[FLATPAK_REMOTE_TYPE_LAN]) + return TRUE; + + /* Find the collection ID for @remote_name, or bail if there is none. */ + if (!ostree_repo_get_remote_option (flatpak_dir_get_repo (dir), + remote_name, "collection-id", + NULL, &collection_id, error)) + return FALSE; + if (collection_id == NULL || *collection_id == '\0') + return TRUE; + + context = flatpak_main_context_new_default (); + + appstream_ref = g_strdup_printf ("appstream/%s", flatpak_get_arch ()); + ref.collection_id = collection_id; + ref.ref_name = appstream_ref; + refs[0] = &ref; + + if (types_filter[FLATPAK_REMOTE_TYPE_USB]) + { + finder_mount = OSTREE_REPO_FINDER (ostree_repo_finder_mount_new (NULL)); + finders[finder_index++] = finder_mount; + } + + if (types_filter[FLATPAK_REMOTE_TYPE_LAN]) + { + g_autoptr(GError) local_error = NULL; + finder_avahi = OSTREE_REPO_FINDER (ostree_repo_finder_avahi_new (context)); + finders[finder_index++] = finder_avahi; + + /* The Avahi finder may fail to start on, for example, a CI server. */ + ostree_repo_finder_avahi_start (OSTREE_REPO_FINDER_AVAHI (finder_avahi), &local_error); + if (local_error != NULL) + { + if (finder_index == 1) + return TRUE; + else + { + finders[--finder_index] = NULL; + g_clear_object (&finder_avahi); + } + } + } + + ostree_repo_find_remotes_async (flatpak_dir_get_repo (dir), + (const OstreeCollectionRef * const *) refs, + NULL, /* no options */ + finders, + NULL, /* no progress */ + cancellable, + async_result_cb, + &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + results = ostree_repo_find_remotes_finish (flatpak_dir_get_repo (dir), result, error); + + if (types_filter[FLATPAK_REMOTE_TYPE_LAN]) + ostree_repo_finder_avahi_stop (OSTREE_REPO_FINDER_AVAHI (finder_avahi)); + + for (i = 0; results != NULL && results[i] != NULL; i++) + { + g_ptr_array_add (remotes, + flatpak_remote_new_from_ostree (results[i]->remote, + results[i]->finder, + dir)); + } +#endif /* FLATPAK_ENABLE_P2P */ + + return TRUE; +} + +/** + * flatpak_installation_list_remotes_by_type: + * @self: a #FlatpakInstallation + * @types: (array length=num_types): an array of #FlatpakRemoteType + * @num_types: the number of types provided in @types + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists only the remotes whose type is included in the @types argument. + * + * Returns: (transfer container) (element-type FlatpakRemote): a GPtrArray of + * #FlatpakRemote instances + */ +GPtrArray * +flatpak_installation_list_remotes_by_type (FlatpakInstallation *self, + const FlatpakRemoteType *types, + gsize num_types, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_autoptr(FlatpakDir) dir_clone = NULL; + g_auto(GStrv) remote_names = NULL; + g_autoptr(GPtrArray) remotes = g_ptr_array_new_with_free_func (g_object_unref); + const guint NUM_FLATPAK_REMOTE_TYPES = 3; + gboolean types_filter[NUM_FLATPAK_REMOTE_TYPES]; + gsize i; + + remote_names = flatpak_dir_list_remotes (dir, cancellable, error); + if (remote_names == NULL) + return NULL; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_maybe_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + for (i = 0; i < NUM_FLATPAK_REMOTE_TYPES; ++i) + { + /* If NULL or an empty array of types is passed then we include all types */ + types_filter[i] = (num_types == 0) ? TRUE : FALSE; + } + + for (i = 0; i < num_types; ++i) + { + g_return_val_if_fail (types[i] < NUM_FLATPAK_REMOTE_TYPES, NULL); + types_filter[types[i]] = TRUE; + } + + for (i = 0; remote_names[i] != NULL; ++i) + { + g_autoptr(GError) local_error = NULL; + if (types_filter[FLATPAK_REMOTE_TYPE_STATIC]) + g_ptr_array_add (remotes, flatpak_remote_new_with_dir (remote_names[i], + dir_clone)); + + /* Add the dynamic mirrors of this remote. */ + if (!list_remotes_for_configured_remote (self, remote_names[i], dir_clone, + types_filter, remotes, + cancellable, &local_error)) + g_debug ("Couldn't find remotes for configured remote %s: %s", + remote_names[i], local_error->message); + } + + return g_steal_pointer (&remotes); +} + +/** + * flatpak_installation_list_remotes: + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists the static remotes, in priority (highest first) order. For same + * priority, an earlier added remote comes before a later added one. + * + * Returns: (transfer container) (element-type FlatpakRemote): an GPtrArray of + * #FlatpakRemote instances + */ +GPtrArray * +flatpak_installation_list_remotes (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + const FlatpakRemoteType types[] = { FLATPAK_REMOTE_TYPE_STATIC }; + return flatpak_installation_list_remotes_by_type (self, types, 1, cancellable, error); +} + +/** + * flatpak_installation_modify_remote: + * @self: a #FlatpakInstallation + * @remote: the modified #FlatpakRemote + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Saves changes in the @remote object. + * + * Returns: %TRUE if the modifications have been committed successfully + */ +gboolean +flatpak_installation_modify_remote (FlatpakInstallation *self, + FlatpakRemote *remote, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_autoptr(FlatpakDir) dir_clone = NULL; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_maybe_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (!flatpak_remote_commit (remote, dir_clone, cancellable, error)) + return FALSE; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + return TRUE; +} + +/** + * flatpak_installation_remove_remote: + * @self: a #FlatpakInstallation + * @name: the name of the remote to remove + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Removes the remote with the given name from the installation. + * + * Returns: %TRUE if the remote has been removed successfully + */ +gboolean +flatpak_installation_remove_remote (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (!flatpak_dir_remove_remote (dir, FALSE, name, + cancellable, error)) + return FALSE; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + return TRUE; +} + +/** + * flatpak_installation_set_config_sync: + * @self: a #FlatpakInstallation + * @key: the name of the key to set + * @value: the new value, or %NULL to unset + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Set a global configuration option for the installation, currently + * the only supported key is "languages", which is a comman-separated + * list of langue codes like "sv;en;pl", or "" to mean all languages. + * + * Returns: %TRUE if the option was set correctly + */ +gboolean +flatpak_installation_set_config_sync (FlatpakInstallation *self, + const char *key, + const char *value, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (!flatpak_dir_set_config (dir, key, value, error)) + return FALSE; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + return TRUE; +} + +/** + * flatpak_installation_get_config: + * @self: a #FlatpakInstallation + * @key: the name of the key to get + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Get a global configuration option for the remote, see + * flatpak_installation_set_config_sync() for supported keys. + * + * Returns: The (newly allocated) value, or %NULL on error (%G_KEY_FILE_ERROR_KEY_NOT_FOUND error if key is not set) + */ +char * +flatpak_installation_get_config (FlatpakInstallation *self, + const char *key, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + return flatpak_dir_get_config (dir, key, error); +} + +/** + * flatpak_installation_update_remote_sync: + * @self: a #FlatpakInstallation + * @name: the name of the remote to update + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Updates the local configuration of a remote repository by fetching + * the related information from the summary file in the remote OSTree + * repository and committing the changes to the local installation. + * + * Returns: %TRUE if the remote has been updated successfully + * + * Since: 0.6.13 + */ +gboolean +flatpak_installation_update_remote_sync (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (!flatpak_dir_update_remote_configuration (dir, name, cancellable, error)) + return FALSE; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + return TRUE; +} + +/** + * flatpak_installation_get_remote_by_name: + * @self: a #FlatpakInstallation + * @name: a remote name + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Looks up a remote by name. + * + * Returns: (transfer full): a #FlatpakRemote instances, or %NULL error + */ +FlatpakRemote * +flatpak_installation_get_remote_by_name (FlatpakInstallation *self, + const gchar *name, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_autoptr(FlatpakDir) dir_clone = NULL; + g_auto(GStrv) remote_names = NULL; + int i; + + remote_names = flatpak_dir_list_remotes (dir, cancellable, error); + if (remote_names == NULL) + return NULL; + + for (i = 0; remote_names[i] != NULL; i++) + { + if (strcmp (remote_names[i], name) == 0) + { + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + return flatpak_remote_new_with_dir (remote_names[i], dir_clone); + } + } + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "No remote named '%s'", name); + return NULL; +} + +/** + * flatpak_installation_load_app_overrides: + * @self: a #FlatpakInstallation + * @app_id: an application id + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Loads the metadata overrides file for an application. + * + * Returns: (transfer full): the contents of the overrides files, + * or %NULL if an error occurred + */ +char * +flatpak_installation_load_app_overrides (FlatpakInstallation *self, + const char *app_id, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autofree char *metadata_contents = NULL; + gsize metadata_size; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + metadata_contents = flatpak_dir_load_override (dir, app_id, &metadata_size, error); + if (metadata_contents == NULL) + return NULL; + + return metadata_contents; +} + +/** + * flatpak_installation_install_bundle: + * @self: a #FlatpakInstallation + * @file: a #GFile that is an flatpak bundle + * @progress: (scope call) (nullable): progress callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Install an application or runtime from an flatpak bundle file. + * See flatpak-build-bundle(1) for how to create bundles. + * + * Returns: (transfer full): The ref for the newly installed app or %NULL on failure + */ +FlatpakInstalledRef * +flatpak_installation_install_bundle (FlatpakInstallation *self, + GFile *file, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autofree char *ref = NULL; + g_autofree char *remote = NULL; + FlatpakInstalledRef *result = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + remote = flatpak_dir_ensure_bundle_remote (dir, file, NULL, &ref, NULL, NULL, cancellable, error); + if (remote == NULL) + return NULL; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + if (!flatpak_dir_install_bundle (dir_clone, file, remote, NULL, + cancellable, error)) + return NULL; + + if (g_str_has_prefix (ref, "app")) + flatpak_dir_run_triggers (dir_clone, cancellable, NULL); + + result = get_ref (dir, ref, cancellable, error); + if (result == NULL) + return NULL; + + return result; +} + +/** + * flatpak_installation_install_ref_file: + * @self: a #FlatpakInstallation + * @ref_file_data: The ref file contents + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a remote based on the passed in .flatpakref file contents + * in @ref_file_data and returns the #FlatpakRemoteRef that can be used + * to install it. + * + * Note, the #FlatpakRemoteRef will not have the commit field set, or other details, to + * avoid unnecessary roundtrips. If you need that you have to resolve it + * explicitly with flatpak_installation_fetch_remote_ref_sync (). + * + * Returns: (transfer full): a #FlatpakRemoteRef if the remote has been added successfully, %NULL + * on error. + * + * Since: 0.6.10 + */ +FlatpakRemoteRef * +flatpak_installation_install_ref_file (FlatpakInstallation *self, + GBytes *ref_file_data, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autofree char *remote = NULL; + g_autofree char *ref = NULL; + g_autofree char *collection_id = NULL; + g_autoptr(FlatpakCollectionRef) coll_ref = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + if (!flatpak_dir_create_remote_for_ref_file (dir, ref_file_data, NULL, &remote, &collection_id, &ref, error)) + return NULL; + + if (!flatpak_installation_drop_caches (self, cancellable, error)) + return NULL; + + coll_ref = flatpak_collection_ref_new (collection_id, ref); + return flatpak_remote_ref_new (coll_ref, NULL, remote, NULL); +} + +/** + * flatpak_installation_install_full: + * @self: a #FlatpakInstallation + * @flags: set of #FlatpakInstallFlags flag + * @remote_name: name of the remote to use + * @kind: what this ref contains (an #FlatpakRefKind) + * @name: name of the app/runtime to fetch + * @arch: (nullable): which architecture to fetch (default: current architecture) + * @branch: (nullable): which branch to fetch (default: 'master') + * @subpaths: (nullable) (array zero-terminated=1): A list of subpaths to fetch, or %NULL for everything + * @progress: (scope call) (nullable): progress callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Install a new application or runtime. + * + * Note that this function was originally written to always return a + * #FlatpakInstalledRef. Since 0.9.13, passing + * FLATPAK_INSTALL_FLAGS_NO_DEPLOY will only pull refs into the local flatpak + * repository without deploying them, however this function will + * be unable to provide information on the installed ref, so + * FLATPAK_ERROR_ONLY_PULLED will be set and the caller must respond + * accordingly. + * + * Returns: (transfer full): The ref for the newly installed app or %NULL on failure + */ +FlatpakInstalledRef * +flatpak_installation_install_full (FlatpakInstallation *self, + FlatpakInstallFlags flags, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + const char * const *subpaths, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autofree char *ref = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(OstreeAsyncProgress) ostree_progress = NULL; + FlatpakInstalledRef *result = NULL; + g_autoptr(GFile) deploy_dir = NULL; + g_autoptr(FlatpakRemoteState) state = NULL; + g_autoptr(GMainContextPopDefault) main_context = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + ref = flatpak_compose_ref (kind == FLATPAK_REF_KIND_APP, name, branch, arch, error); + if (ref == NULL) + return NULL; + + deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, cancellable); + if (deploy_dir != NULL) + { + g_set_error (error, + FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED, + "%s branch %s already installed", name, branch ? branch : "master"); + return NULL; + } + + state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error); + if (state == NULL) + return NULL; + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + /* Work around ostree-pull spinning the default main context for the sync calls */ + main_context = flatpak_main_context_new_default (); + + if (progress) + ostree_progress = flatpak_progress_new (progress, progress_data); + else + ostree_progress = ostree_async_progress_new_and_connect (no_progress_cb, NULL); + + if (!flatpak_dir_install (dir_clone, + (flags & FLATPAK_INSTALL_FLAGS_NO_PULL) != 0, + (flags & FLATPAK_INSTALL_FLAGS_NO_DEPLOY) != 0, + (flags & FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS) != 0, + FALSE, state, + ref, (const char **)subpaths, + ostree_progress, cancellable, error)) + goto out; + + if (g_str_has_prefix (ref, "app")) + flatpak_dir_run_triggers (dir_clone, cancellable, NULL); + + /* Note that if the caller sets FLATPAK_INSTALL_FLAGS_NO_DEPLOY we must + * always return an error, as explained above. Otherwise get_ref will + * always return an error. */ + if ((flags & FLATPAK_INSTALL_FLAGS_NO_DEPLOY) != 0) + { + g_set_error (error, + FLATPAK_ERROR, FLATPAK_ERROR_ONLY_PULLED, + "As requested, %s was only pulled, but not installed", + name); + goto out; + } + + result = get_ref (dir, ref, cancellable, error); + if (result == NULL) + goto out; + +out: + if (ostree_progress) + ostree_async_progress_finish (ostree_progress); + + return result; +} + +/** + * flatpak_installation_install: + * @self: a #FlatpakInstallation + * @remote_name: name of the remote to use + * @kind: what this ref contains (an #FlatpakRefKind) + * @name: name of the app/runtime to fetch + * @arch: (nullable): which architecture to fetch (default: current architecture) + * @branch: (nullable): which branch to fetch (default: 'master') + * @progress: (scope call) (nullable): progress callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Install a new application or runtime. + * + * Note that this function was originally written to always return a + * #FlatpakInstalledRef. Since 0.9.13, passing + * FLATPAK_INSTALL_FLAGS_NO_DEPLOY will only pull refs into the local flatpak + * repository without deploying them, however this function will + * be unable to provide information on the installed ref, so + * FLATPAK_ERROR_ONLY_PULLED will be set and the caller must respond + * accordingly. + * + * Returns: (transfer full): The ref for the newly installed app or %NULL on failure + */ +FlatpakInstalledRef * +flatpak_installation_install (FlatpakInstallation *self, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_install_full (self, FLATPAK_INSTALL_FLAGS_NONE, + remote_name, kind, name, arch, branch, + NULL, progress, progress_data, + cancellable, error); +} + +/** + * flatpak_installation_update_full: + * @self: a #FlatpakInstallation + * @flags: set of #FlatpakUpdateFlags flag + * @kind: whether this is an app or runtime + * @name: name of the app or runtime to update + * @arch: (nullable): architecture of the app or runtime to update (default: current architecture) + * @branch: (nullable): name of the branch of the app or runtime to update (default: master) + * @subpaths: (nullable) (array zero-terminated=1): A list of subpaths to fetch, or %NULL for everything + * @progress: (scope call) (nullable): the callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Update an application or runtime. + * + * If the specified package is not installed, then %FLATPAK_ERROR_NOT_INSTALLED + * will be thrown. + * + * If no updates could be found on the remote end and the package is + * already up to date, then %FLATPAK_ERROR_ALREADY_INSTALLED will be thrown. + * + * Returns: (transfer full): The ref for the newly updated app or %NULL on failure + */ +FlatpakInstalledRef * +flatpak_installation_update_full (FlatpakInstallation *self, + FlatpakUpdateFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + const char * const *subpaths, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autofree char *ref = NULL; + g_autoptr(GFile) deploy_dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(OstreeAsyncProgress) ostree_progress = NULL; + g_autofree char *remote_name = NULL; + FlatpakInstalledRef *result = NULL; + g_autofree char *target_commit = NULL; + g_auto(OstreeRepoFinderResultv) check_results = NULL; + g_autoptr(FlatpakRemoteState) state = NULL; + g_autoptr(GMainContextPopDefault) main_context = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + ref = flatpak_compose_ref (kind == FLATPAK_REF_KIND_APP, name, branch, arch, error); + if (ref == NULL) + return NULL; + + deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, cancellable); + if (deploy_dir == NULL) + { + g_set_error (error, + FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + "%s branch %s is not installed", name, branch ? branch : "master"); + return NULL; + } + + remote_name = flatpak_dir_get_origin (dir, ref, cancellable, error); + if (remote_name == NULL) + return NULL; + + state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error); + if (state == NULL) + return NULL; + + target_commit = flatpak_dir_check_for_update (dir, state, ref, NULL, + (const char **)subpaths, + (flags & FLATPAK_UPDATE_FLAGS_NO_PULL) != 0, + &check_results, + cancellable, error); + if (target_commit == NULL) + return NULL; + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + /* Work around ostree-pull spinning the default main context for the sync calls */ + main_context = flatpak_main_context_new_default (); + + if (progress) + ostree_progress = flatpak_progress_new (progress, progress_data); + else + ostree_progress = ostree_async_progress_new_and_connect (no_progress_cb, NULL); + + if (!flatpak_dir_update (dir_clone, + (flags & FLATPAK_UPDATE_FLAGS_NO_PULL) != 0, + (flags & FLATPAK_UPDATE_FLAGS_NO_DEPLOY) != 0, + (flags & FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS) != 0, + FALSE, state, + ref, target_commit, + (const OstreeRepoFinderResult * const *) check_results, + (const char **)subpaths, + ostree_progress, cancellable, error)) + goto out; + + if (g_str_has_prefix (ref, "app")) + flatpak_dir_run_triggers (dir_clone, cancellable, NULL); + + result = get_ref (dir, ref, cancellable, error); + if (result == NULL) + goto out; + + /* We don't get prunable objects if not pulling or if NO_PRUNE is passed */ + if (!(flags & FLATPAK_UPDATE_FLAGS_NO_PULL) && !(flags & FLATPAK_UPDATE_FLAGS_NO_PRUNE)) + flatpak_dir_prune (dir_clone, cancellable, NULL); + +out: + if (ostree_progress) + ostree_async_progress_finish (ostree_progress); + + return result; +} + +/** + * flatpak_installation_update: + * @self: a #FlatpakInstallation + * @flags: set of #FlatpakUpdateFlags flag + * @kind: whether this is an app or runtime + * @name: name of the app or runtime to update + * @arch: (nullable): architecture of the app or runtime to update (default: current architecture) + * @branch: (nullable): name of the branch of the app or runtime to update (default: master) + * @progress: (scope call) (nullable): the callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Update an application or runtime. + * + * If the specified package is not installed, then %FLATPAK_ERROR_NOT_INSTALLED + * will be thrown. + * + * If no updates could be found on the remote end and the package is + * already up to date, then %FLATPAK_ERROR_ALREADY_INSTALLED will be thrown. + * + * Returns: (transfer full): The ref for the newly updated app or %NULL on failure + */ +FlatpakInstalledRef * +flatpak_installation_update (FlatpakInstallation *self, + FlatpakUpdateFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_update_full (self, flags, kind, name, arch, + branch, NULL, progress, progress_data, + cancellable, error); +} + +/** + * flatpak_installation_uninstall: + * @self: a #FlatpakInstallation + * @kind: what this ref contains (an #FlatpakRefKind) + * @name: name of the app or runtime to uninstall + * @arch: architecture of the app or runtime to uninstall + * @branch: name of the branch of the app or runtime to uninstall + * @progress: (scope call) (nullable): the callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Uninstall an application or runtime. + * + * Returns: %TRUE on success + */ +FLATPAK_EXTERN gboolean +flatpak_installation_uninstall (FlatpakInstallation *self, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_uninstall_full (self, FLATPAK_UNINSTALL_FLAGS_NONE, + kind, name, arch, branch, + progress, progress_data, + cancellable, error); +} + +/** + * flatpak_installation_uninstall_full: + * @self: a #FlatpakInstallation + * @flags: set of #FlatpakUninstallFlags flags + * @kind: what this ref contains (an #FlatpakRefKind) + * @name: name of the app or runtime to uninstall + * @arch: architecture of the app or runtime to uninstall + * @branch: name of the branch of the app or runtime to uninstall + * @progress: (scope call) (nullable): the callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Uninstall an application or runtime. + * + * Returns: %TRUE on success + * + * Since: 0.11.8 + */ +gboolean +flatpak_installation_uninstall_full (FlatpakInstallation *self, + FlatpakUninstallFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autofree char *ref = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + ref = flatpak_compose_ref (kind == FLATPAK_REF_KIND_APP, name, branch, arch, error); + if (ref == NULL) + return FALSE; + + /* prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (!flatpak_dir_uninstall (dir_clone, ref, FLATPAK_HELPER_UNINSTALL_FLAGS_NONE, + cancellable, error)) + return FALSE; + + if (g_str_has_prefix (ref, "app")) + flatpak_dir_run_triggers (dir_clone, cancellable, NULL); + + if (!(flags & FLATPAK_UNINSTALL_FLAGS_NO_PRUNE)) + flatpak_dir_prune (dir_clone, cancellable, NULL); + + return TRUE; +} + +/** + * flatpak_installation_fetch_remote_size_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @ref: the ref + * @download_size: (out): return location for the (maximum) download size + * @installed_size: (out): return location for the installed size + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Gets information about the maximum amount of data that needs to be transferred + * to pull the ref from a remote repository, and about the amount of + * local disk space that is required to check out this commit. + * + * Note that if there are locally available data that are in the ref, which is common + * for instance if you're doing an update then the real download size may be smaller + * than what is returned here. + * + * NOTE: Since 0.11.4 this information is accessible in FlatpakRemoteRef, so this + * function is not very useful anymore. + * + * Returns: %TRUE, unless an error occurred + */ +gboolean +flatpak_installation_fetch_remote_size_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRef *ref, + guint64 *download_size, + guint64 *installed_size, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakRemoteState) state = NULL; + g_autofree char *full_ref = flatpak_ref_format_ref (ref); + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error); + if (state == NULL) + return FALSE; + + return flatpak_remote_state_lookup_cache (state, full_ref, + download_size, installed_size, NULL, + error); +} + +/** + * flatpak_installation_fetch_remote_metadata_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @ref: the ref + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Obtains the metadata file from a commit. + * + * NOTE: Since 0.11.4 this information is accessible in FlatpakRemoteRef, so this + * function is not very useful anymore. + * + * Returns: (transfer full): a #GBytes containing the flatpak metadata file, + * or %NULL if an error occurred + */ +GBytes * +flatpak_installation_fetch_remote_metadata_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRef *ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakRemoteState) state = NULL; + g_autofree char *full_ref = flatpak_ref_format_ref (ref); + const char *res = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error); + if (state == NULL) + return FALSE; + + if (!flatpak_remote_state_lookup_cache (state, full_ref, + NULL, NULL, &res, + error)) + return NULL; + + return g_bytes_new (res, strlen (res)); +} + +/** + * flatpak_installation_list_remote_refs_sync: + * @self: a #FlatpakInstallation + * @remote_or_uri: the name or URI of the remote + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists all the applications and runtimes in a remote. + * + * Returns: (transfer container) (element-type FlatpakRemoteRef): a GPtrArray of + * #FlatpakRemoteRef instances + */ +GPtrArray * +flatpak_installation_list_remote_refs_sync (FlatpakInstallation *self, + const char *remote_or_uri, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_object_unref); + g_autoptr(FlatpakRemoteState) state = NULL; + g_autoptr(GHashTable) ht = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + state = flatpak_dir_get_remote_state (dir, remote_or_uri, cancellable, error); + if (state == NULL) + return NULL; + + if (!flatpak_dir_list_remote_refs (dir, state, &ht, + cancellable, error)) + return NULL; + + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + FlatpakRemoteRef *ref; + FlatpakCollectionRef *coll_ref = key; + const gchar *ref_commit = value; + + ref = flatpak_remote_ref_new (coll_ref, ref_commit, remote_or_uri, state); + + if (ref) + g_ptr_array_add (refs, ref); + } + + return g_steal_pointer (&refs); +} + +/** + * flatpak_installation_fetch_remote_ref_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @kind: what this ref contains (an #FlatpakRefKind) + * @name: name of the app/runtime to fetch + * @arch: (nullable): which architecture to fetch (default: current architecture) + * @branch: (nullable): which branch to fetch (default: 'master') + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Gets the current remote branch of a ref in the remote. + * + * Returns: (transfer full): a #FlatpakRemoteRef instance, or %NULL + */ +FlatpakRemoteRef * +flatpak_installation_fetch_remote_ref_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GHashTable) ht = NULL; + g_autoptr(FlatpakRemoteState) state = NULL; + g_autofree char *ref = NULL; + g_autoptr(FlatpakCollectionRef) coll_ref = NULL; + g_autofree gchar *collection_id = NULL; + const char *checksum; + + if (branch == NULL) + branch = "master"; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + state = flatpak_dir_get_remote_state (dir, remote_name, cancellable, error); + if (state == NULL) + return NULL; + + if (!flatpak_dir_list_remote_refs (dir, state, &ht, + cancellable, error)) + return NULL; + + /* FIXME: Rework to accept the collection ID as an input argument instead */ +#ifdef FLATPAK_ENABLE_P2P + if (!ostree_repo_get_remote_option (flatpak_dir_get_repo (dir), + remote_name, "collection-id", + NULL, &collection_id, error)) + return FALSE; +#endif /* FLATPAK_ENABLE_P2P */ + + if (kind == FLATPAK_REF_KIND_APP) + ref = flatpak_build_app_ref (name, + branch, + arch); + else + ref = flatpak_build_runtime_ref (name, + branch, + arch); + + coll_ref = flatpak_collection_ref_new (collection_id, ref); + checksum = g_hash_table_lookup (ht, coll_ref); + +#ifdef FLATPAK_ENABLE_P2P + /* If there was not a match, it may be because the collection ID is + * not set in the local configuration, or it is wrong, so we resort to + * trying to match just the ref name */ + if (checksum == NULL) + { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + FlatpakCollectionRef *current = (FlatpakCollectionRef *) key; + if (g_strcmp0 (current->ref_name, ref) == 0) + { + checksum = (const gchar *) value; + break; + } + } + } +#endif /* FLATPAK_ENABLE_P2P */ + + if (checksum != NULL) + return flatpak_remote_ref_new (coll_ref, checksum, remote_name, state); + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Reference %s doesn't exist in remote", ref); + return NULL; +} + +/** + * flatpak_installation_update_appstream_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @arch: Architecture to update, or %NULL for the local machine arch + * @out_changed: (nullable): Set to %TRUE if the contents of the appstream changed, %FALSE if nothing changed + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Updates the local copy of appstream for @remote_name for the specified @arch. + * If you need progress feedback, use flatpak_installation_update_appstream_full_sync(). + * + * Returns: %TRUE on success, or %FALSE on error + */ +gboolean +flatpak_installation_update_appstream_sync (FlatpakInstallation *self, + const char *remote_name, + const char *arch, + gboolean *out_changed, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_update_appstream_full_sync (self, remote_name, arch, + NULL, NULL, out_changed, + cancellable, error); + +} + +/** + * flatpak_installation_update_appstream_full_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @arch: Architecture to update, or %NULL for the local machine arch + * @progress: (scope call) (nullable): progress callback + * @progress_data: (closure progress) (nullable): user data passed to @progress + * @out_changed: (nullable): Set to %TRUE if the contents of the appstream changed, %FALSE if nothing changed + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Updates the local copy of appstream for @remote_name for the specified @arch. + * + * Returns: %TRUE on success, or %FALSE on error + */ +gboolean +flatpak_installation_update_appstream_full_sync (FlatpakInstallation *self, + const char *remote_name, + const char *arch, + FlatpakProgressCallback progress, + gpointer progress_data, + gboolean *out_changed, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(OstreeAsyncProgress) ostree_progress = NULL; + gboolean res; + g_autoptr(GMainContextPopDefault) main_context = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + /* Work around ostree-pull spinning the default main context for the sync calls */ + main_context = flatpak_main_context_new_default (); + + if (progress) + ostree_progress = flatpak_progress_new (progress, progress_data); + else + ostree_progress = ostree_async_progress_new_and_connect (no_progress_cb, NULL); + + res = flatpak_dir_update_appstream (dir_clone, + remote_name, + arch, + out_changed, + ostree_progress, + cancellable, + error); + + if (ostree_progress) + ostree_async_progress_finish (ostree_progress); + + return res; +} + + +/** + * flatpak_installation_create_monitor: + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Gets monitor object for the installation. The returned file monitor will + * emit the #GFileMonitor::changed signal whenever an application or runtime + * was installed, uninstalled or updated. + * + * Returns: (transfer full): a new #GFileMonitor instance, or %NULL on error + */ +GFileMonitor * +flatpak_installation_create_monitor (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_autoptr(GFile) path = NULL; + + path = flatpak_dir_get_changed_path (dir); + + return g_file_monitor_file (path, G_FILE_MONITOR_NONE, + cancellable, error); +} + + +/** + * flatpak_installation_list_remote_related_refs_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @ref: the ref + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists all the available refs on @remote_name that are related to + * @ref, and the subpaths to use. These are things that are + * interesting to install, update, or uninstall together with + * @ref. For instance, locale data or debug information. + * + * The returned list contains all available related refs, but not + * everyone should always be installed. For example, + * flatpak_related_ref_should_download () returns TRUE if the + * reference should be installed/updated with the app, and + * flatpak_related_ref_should_delete () returns TRUE if it + * should be uninstalled with the main ref. + * + * The commit property of each FlatpakRelatedRef is not guaranteed to be + * non-%NULL. + * + * Returns: (transfer container) (element-type FlatpakRelatedRef): a GPtrArray of + * #FlatpakRelatedRef instances + * + * Since: 0.6.7 + */ +GPtrArray * +flatpak_installation_list_remote_related_refs_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GPtrArray) related = NULL; + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_object_unref); + g_autoptr(FlatpakRemoteState) state = NULL; + int i; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error); + if (state == NULL) + return NULL; + + related = flatpak_dir_find_remote_related (dir, state, ref, + cancellable, error); + if (related == NULL) + return NULL; + + for (i = 0; i < related->len; i++) + { + FlatpakRelated *rel = g_ptr_array_index (related, i); + FlatpakRelatedRef *ref; + + ref = flatpak_related_ref_new (rel->collection_id, rel->ref, rel->commit, + rel->subpaths, rel->download, rel->delete); + + if (ref) + g_ptr_array_add (refs, ref); + } + + return g_steal_pointer (&refs); +} + +/** + * flatpak_installation_list_installed_related_refs_sync: + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @ref: the ref + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Lists all the locally installed refs from @remote_name that are + * related to @ref. These are things that are interesting to install, + * update, or uninstall together with @ref. For instance, locale data + * or debug information. + * + * This function is similar to flatpak_installation_list_remote_related_refs_sync, + * but instead of looking at what is available on the remote, it only looks + * at the locally installed refs. This is useful for instance when you're + * looking for related refs to uninstall, or when you're planning to use + * FLATPAK_UPDATE_FLAGS_NO_PULL to install previously pulled refs. + * + * Returns: (transfer container) (element-type FlatpakRelatedRef): a GPtrArray of + * #FlatpakRelatedRef instances + * + * Since: 0.6.7 + */ +GPtrArray * +flatpak_installation_list_installed_related_refs_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GPtrArray) related = NULL; + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_object_unref); + int i; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + related = flatpak_dir_find_local_related (dir, ref, remote_name, TRUE, + cancellable, error); + if (related == NULL) + return NULL; + + for (i = 0; i < related->len; i++) + { + FlatpakRelated *rel = g_ptr_array_index (related, i); + FlatpakRelatedRef *ref; + + ref = flatpak_related_ref_new (rel->collection_id, rel->ref, rel->commit, + rel->subpaths, rel->download, rel->delete); + + if (ref) + g_ptr_array_add (refs, ref); + } + + return g_steal_pointer (&refs); +} + +/** + * flatpak_installation_remove_local_ref_sync + * @self: a #FlatpakInstallation + * @remote_name: the name of the remote + * @ref: the ref + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Remove the OSTree ref given by @remote_name:@ref from the local flatpak + * repository. The next time the underlying OSTree repo is pruned, objects + * which were attached to that ref will be removed. This is useful if you + * pulled a flatpak ref using flatpak_installation_install_full() and + * specified %FLATPAK_INSTALL_FLAGS_NO_DEPLOY but then decided not to + * deploy the ref later on and want to remove the local ref to prevent it + * from taking up disk space. Note that this will not remove the objects + * referred to by @ref from the underlying OSTree repo, you should use + * flatpak_installation_prune_local_repo() to do that. + * + * Returns: %TRUE on success + */ +gboolean +flatpak_installation_remove_local_ref_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + return flatpak_dir_remove_ref (dir, remote_name, ref, cancellable, error); +} + +/** + * flatpak_installation_cleanup_local_refs_sync + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Remove all OSTree refs from the local flatpak repository which are not + * in a deployed state. The next time the underlying OSTree repo is pruned, + * objects which were attached to that ref will be removed. This is useful if + * you pulled a flatpak refs using flatpak_installation_install_full() and + * specified %FLATPAK_INSTALL_FLAGS_NO_DEPLOY but then decided not to + * deploy the refs later on and want to remove the local refs to prevent them + * from taking up disk space. Note that this will not remove the objects + * referred to by @ref from the underlying OSTree repo, you should use + * flatpak_installation_prune_local_repo() to do that. + * + * Since: 0.10.0 + * Returns: %TRUE on success + */ +gboolean +flatpak_installation_cleanup_local_refs_sync (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + return flatpak_dir_cleanup_undeployed_refs (dir, cancellable, error); +} + +/** + * flatpak_installation_prune_local_repo + * @self: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Remove all orphaned OSTree objects from the underlying OSTree repo in + * @installation. + * + * Returns: %TRUE on success + */ +gboolean +flatpak_installation_prune_local_repo (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return FALSE; + + return flatpak_dir_prune (dir, cancellable, error); +} diff -Nru flatpak-0.11.7/common/flatpak-installation.h flatpak-0.11.8.3/common/flatpak-installation.h --- flatpak-0.11.7/common/flatpak-installation.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installation.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,373 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_INSTALLATION_H__ +#define __FLATPAK_INSTALLATION_H__ + +typedef struct _FlatpakInstallation FlatpakInstallation; + +#include +#include +#include + +#define FLATPAK_TYPE_INSTALLATION flatpak_installation_get_type () +#define FLATPAK_INSTALLATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_INSTALLATION, FlatpakInstallation)) +#define FLATPAK_IS_INSTALLATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_INSTALLATION)) + +FLATPAK_EXTERN GType flatpak_installation_get_type (void); + +struct _FlatpakInstallation +{ + GObject parent; +}; + +typedef struct +{ + GObjectClass parent_class; +} FlatpakInstallationClass; + +/** + * FlatpakUpdateFlags: + * @FLATPAK_UPDATE_FLAGS_NONE: Fetch remote builds and install the latest one (default) + * @FLATPAK_UPDATE_FLAGS_NO_DEPLOY: Don't install any new builds that might be fetched + * @FLATPAK_UPDATE_FLAGS_NO_PULL: Don't try to fetch new builds from the remote repo + * @FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS: Don't use static deltas when pulling + * @FLATPAK_UPDATE_FLAGS_NO_PRUNE: Don't prune the local OSTree repository after updating (Since: 0.11.8) + * + * Flags to alter the behavior of flatpak_installation_update(). + */ +typedef enum { + FLATPAK_UPDATE_FLAGS_NONE = 0, + FLATPAK_UPDATE_FLAGS_NO_DEPLOY = (1 << 0), + FLATPAK_UPDATE_FLAGS_NO_PULL = (1 << 1), + FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS = (1 << 2), + FLATPAK_UPDATE_FLAGS_NO_PRUNE = (1 << 3), +} FlatpakUpdateFlags; + +/** + * FlatpakInstallFlags: + * @FLATPAK_INSTALL_FLAGS_NONE: Default + * @FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS: Don't use static deltas when pulling + * @FLATPAK_INSTALL_FLAGS_NO_DEPLOY: Don't install any new builds that might be fetched + * @FLATPAK_INSTALL_FLAGS_NO_PULL: Don't try to fetch new builds from the remote repo + * + * Flags to alter the behavior of flatpak_installation_install_full(). + */ +typedef enum { + FLATPAK_INSTALL_FLAGS_NONE = 0, + FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS = (1 << 0), + FLATPAK_INSTALL_FLAGS_NO_DEPLOY = (1 << 2), + FLATPAK_INSTALL_FLAGS_NO_PULL = (1 << 3), +} FlatpakInstallFlags; + +/** + * FlatpakUninstallFlags: + * @FLATPAK_UNINSTALL_FLAGS_NONE: Default + * @FLATPAK_UNINSTALL_FLAGS_NO_PRUNE: Don't prune the local OSTree repository after uninstalling + * + * Flags to alter the behavior of flatpak_installation_uninstall_full(). + * + * Since: 0.11.8 + */ +typedef enum { + FLATPAK_UNINSTALL_FLAGS_NONE = 0, + FLATPAK_UNINSTALL_FLAGS_NO_PRUNE = (1 << 0), +} FlatpakUninstallFlags; + +/** + * FlatpakStorageType: + * @FLATPAK_STORAGE_TYPE_DEFAULT: default + * @FLATPAK_STORAGE_TYPE_HARD_DISK: installation is on a hard disk + * @FLATPAK_STORAGE_TYPE_SDCARD: installation is on a SD card + * @FLATPAK_STORAGE_TYPE_MMC: installation is on an MMC + * @FLATPAK_STORAGE_TYPE_NETWORK: installation is on the network + * + * Flags to alter the behavior of flatpak_installation_install_full(). + * + * Since: 0.6.15 + */ +typedef enum { + FLATPAK_STORAGE_TYPE_DEFAULT = 0, + FLATPAK_STORAGE_TYPE_HARD_DISK, + FLATPAK_STORAGE_TYPE_SDCARD, + FLATPAK_STORAGE_TYPE_MMC, + FLATPAK_STORAGE_TYPE_NETWORK, +} FlatpakStorageType; + + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakInstallation, g_object_unref) +#endif + +FLATPAK_EXTERN const char *flatpak_get_default_arch (void); + +FLATPAK_EXTERN const char *const *flatpak_get_supported_arches (void); + +FLATPAK_EXTERN GPtrArray *flatpak_get_system_installations (GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstallation *flatpak_installation_new_system (GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstallation *flatpak_installation_new_system_with_id (const char *id, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstallation *flatpak_installation_new_user (GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstallation *flatpak_installation_new_for_path (GFile *path, + gboolean user, + GCancellable *cancellable, + GError **error); + +/** + * FlatpakProgressCallback: + * @status: A status string, suitable for display + * @progress: percentage of completion + * @estimating: whether @progress is just an estimate + * @user_data: User data passed to the caller + * + * The progress callback is called repeatedly during long-running operations + * such as installations or updates, and can be used to update progress information + * in a user interface. + * + * The callback occurs in the thread-default context of the caller. + */ +typedef void (*FlatpakProgressCallback)(const char *status, + guint progress, + gboolean estimating, + gpointer user_data); + +FLATPAK_EXTERN gboolean flatpak_installation_drop_caches (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_get_is_user (FlatpakInstallation *self); +FLATPAK_EXTERN GFile *flatpak_installation_get_path (FlatpakInstallation *self); +FLATPAK_EXTERN const char *flatpak_installation_get_id (FlatpakInstallation *self); +FLATPAK_EXTERN const char *flatpak_installation_get_display_name (FlatpakInstallation *self); +FLATPAK_EXTERN gint flatpak_installation_get_priority (FlatpakInstallation *self); +FLATPAK_EXTERN FlatpakStorageType flatpak_installation_get_storage_type (FlatpakInstallation *self); +FLATPAK_EXTERN gboolean flatpak_installation_launch (FlatpakInstallation *self, + const char *name, + const char *arch, + const char *branch, + const char *commit, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GFileMonitor *flatpak_installation_create_monitor (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray *flatpak_installation_list_installed_refs (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray *flatpak_installation_list_installed_refs_by_kind (FlatpakInstallation *self, + FlatpakRefKind kind, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray *flatpak_installation_list_installed_refs_for_update (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_get_installed_ref (FlatpakInstallation *self, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_get_current_installed_app (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error); + +FLATPAK_EXTERN GPtrArray *flatpak_installation_list_remotes (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray *flatpak_installation_list_remotes_by_type (FlatpakInstallation *self, + const FlatpakRemoteType types[], + gsize num_types, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakRemote *flatpak_installation_get_remote_by_name (FlatpakInstallation *self, + const gchar *name, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_modify_remote (FlatpakInstallation *self, + FlatpakRemote *remote, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_remove_remote (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_update_remote_sync (FlatpakInstallation *self, + const char *name, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_set_config_sync (FlatpakInstallation *self, + const char *key, + const char *value, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN char * flatpak_installation_get_config (FlatpakInstallation *self, + const char *key, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN char * flatpak_installation_load_app_overrides (FlatpakInstallation *self, + const char *app_id, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_install (FlatpakInstallation *self, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_install_full (FlatpakInstallation *self, + FlatpakInstallFlags flags, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + const char * const *subpaths, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_update (FlatpakInstallation *self, + FlatpakUpdateFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_update_full (FlatpakInstallation *self, + FlatpakUpdateFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + const char * const *subpaths, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_install_bundle (FlatpakInstallation *self, + GFile *file, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakRemoteRef * flatpak_installation_install_ref_file (FlatpakInstallation *self, + GBytes *ref_file_data, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_uninstall (FlatpakInstallation *self, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); + +FLATPAK_EXTERN gboolean flatpak_installation_uninstall_full (FlatpakInstallation *self, + FlatpakUninstallFlags flags, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + FlatpakProgressCallback progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); + +FLATPAK_EXTERN gboolean flatpak_installation_fetch_remote_size_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRef *ref, + guint64 *download_size, + guint64 *installed_size, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GBytes * flatpak_installation_fetch_remote_metadata_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRef *ref, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray * flatpak_installation_list_remote_refs_sync (FlatpakInstallation *self, + const char *remote_or_uri, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN FlatpakRemoteRef *flatpak_installation_fetch_remote_ref_sync (FlatpakInstallation *self, + const char *remote_name, + FlatpakRefKind kind, + const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_update_appstream_sync (FlatpakInstallation *self, + const char *remote_name, + const char *arch, + gboolean *out_changed, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_update_appstream_full_sync (FlatpakInstallation *self, + const char *remote_name, + const char *arch, + FlatpakProgressCallback progress, + gpointer progress_data, + gboolean *out_changed, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray * flatpak_installation_list_remote_related_refs_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN GPtrArray * flatpak_installation_list_installed_related_refs_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error); + +FLATPAK_EXTERN gboolean flatpak_installation_remove_local_ref_sync (FlatpakInstallation *self, + const char *remote_name, + const char *ref, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_cleanup_local_refs_sync (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_prune_local_repo (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); + + +#endif /* __FLATPAK_INSTALLATION_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-installation-private.h flatpak-0.11.8.3/common/flatpak-installation-private.h --- flatpak-0.11.7/common/flatpak-installation-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installation-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,38 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_INSTALLATION_PRIVATE_H__ +#define __FLATPAK_INSTALLATION_PRIVATE_H__ + +#include "flatpak-installation.h" + +#include "flatpak-dir-private.h" + +FlatpakDir * +flatpak_installation_clone_dir (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); + +FlatpakInstallation * +flatpak_installation_new_for_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error); + +#endif /* __FLATPAK_INSTALLATION_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-installed-ref.c flatpak-0.11.8.3/common/flatpak-installed-ref.c --- flatpak-0.11.7/common/flatpak-installed-ref.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installed-ref.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,469 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include + +#include "flatpak-utils-private.h" +#include "flatpak-installed-ref.h" +#include "flatpak-installed-ref-private.h" +#include "flatpak-enum-types.h" + +/** + * SECTION:flatpak-installed-ref + * @Title: FlatpakInstalledRef + * @Short_description: Installed application reference + * + * A FlatpakInstalledRef provides information about an installed + * application or runtime (in short: ref), such as the available + * builds, its size, location, etc. + */ + +typedef struct _FlatpakInstalledRefPrivate FlatpakInstalledRefPrivate; + +struct _FlatpakInstalledRefPrivate +{ + gboolean is_current; + char *origin; + char *latest_commit; + char *deploy_dir; + char **subpaths; + guint64 installed_size; + char *eol; + char *eol_rebase; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakInstalledRef, flatpak_installed_ref, FLATPAK_TYPE_REF) + +enum { + PROP_0, + + PROP_IS_CURRENT, + PROP_ORIGIN, + PROP_LATEST_COMMIT, + PROP_DEPLOY_DIR, + PROP_INSTALLED_SIZE, + PROP_SUBPATHS, + PROP_EOL, + PROP_EOL_REBASE, +}; + +static void +flatpak_installed_ref_finalize (GObject *object) +{ + FlatpakInstalledRef *self = FLATPAK_INSTALLED_REF (object); + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + g_free (priv->origin); + g_free (priv->latest_commit); + g_free (priv->deploy_dir); + g_strfreev (priv->subpaths); + g_free (priv->eol); + g_free (priv->eol_rebase); + + G_OBJECT_CLASS (flatpak_installed_ref_parent_class)->finalize (object); +} + +static void +flatpak_installed_ref_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakInstalledRef *self = FLATPAK_INSTALLED_REF (object); + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_IS_CURRENT: + priv->is_current = g_value_get_boolean (value); + break; + + case PROP_INSTALLED_SIZE: + priv->installed_size = g_value_get_uint64 (value); + break; + + case PROP_ORIGIN: + g_clear_pointer (&priv->origin, g_free); + priv->origin = g_value_dup_string (value); + break; + + case PROP_LATEST_COMMIT: + g_clear_pointer (&priv->latest_commit, g_free); + priv->latest_commit = g_value_dup_string (value); + break; + + case PROP_DEPLOY_DIR: + g_clear_pointer (&priv->deploy_dir, g_free); + priv->deploy_dir = g_value_dup_string (value); + break; + + case PROP_SUBPATHS: + g_clear_pointer (&priv->subpaths, g_strfreev); + priv->subpaths = g_strdupv (g_value_get_boxed (value)); + break; + + case PROP_EOL: + g_clear_pointer (&priv->eol, g_free); + priv->eol = g_value_dup_string (value); + break; + + case PROP_EOL_REBASE: + g_clear_pointer (&priv->eol_rebase, g_free); + priv->eol_rebase = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_installed_ref_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakInstalledRef *self = FLATPAK_INSTALLED_REF (object); + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_IS_CURRENT: + g_value_set_boolean (value, priv->is_current); + break; + + case PROP_INSTALLED_SIZE: + g_value_set_uint64 (value, priv->installed_size); + break; + + case PROP_ORIGIN: + g_value_set_string (value, priv->origin); + break; + + case PROP_LATEST_COMMIT: + g_value_set_string (value, priv->latest_commit); + break; + + case PROP_DEPLOY_DIR: + g_value_set_string (value, priv->deploy_dir); + break; + + case PROP_SUBPATHS: + g_value_set_boxed (value, priv->subpaths); + break; + + case PROP_EOL: + g_value_set_string (value, priv->eol); + break; + + case PROP_EOL_REBASE: + g_value_set_string (value, priv->eol_rebase); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_installed_ref_class_init (FlatpakInstalledRefClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_installed_ref_get_property; + object_class->set_property = flatpak_installed_ref_set_property; + object_class->finalize = flatpak_installed_ref_finalize; + + g_object_class_install_property (object_class, + PROP_IS_CURRENT, + g_param_spec_boolean ("is-current", + "Is Current", + "Whether the application is current", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_INSTALLED_SIZE, + g_param_spec_uint64 ("installed-size", + "Installed Size", + "The installed size of the application", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_ORIGIN, + g_param_spec_string ("origin", + "Origin", + "The origin", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_LATEST_COMMIT, + g_param_spec_string ("latest-commit", + "Latest Commit", + "The latest commit", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_DEPLOY_DIR, + g_param_spec_string ("deploy-dir", + "Deploy Dir", + "Where the application is installed", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_SUBPATHS, + g_param_spec_boxed ("subpaths", + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_EOL, + g_param_spec_string ("end-of-life", + "End of life", + "The reason for the ref to be end of life", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_EOL_REBASE, + g_param_spec_string ("end-of-life-rebase", + "End of life rebase", + "The new ref for the end of lifeed ref", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); +} + +static void +flatpak_installed_ref_init (FlatpakInstalledRef *self) +{ +} + +/** + * flatpak_installed_ref_get_origin: + * @self: a #FlatpakInstalledRef + * + * Gets the origin of the ref. + * + * Returns: (transfer none): the origin + */ +const char * +flatpak_installed_ref_get_origin (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->origin; +} + +/** + * flatpak_installed_ref_get_latest_commit: + * @self: a #FlatpakInstalledRef + * + * Gets the latest commit of the ref. + * + * Returns: (transfer none): the latest commit + */ +const char * +flatpak_installed_ref_get_latest_commit (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->latest_commit; +} + +/** + * flatpak_installed_ref_get_deploy_dir: + * @self: a #FlatpakInstalledRef + * + * Gets the deploy dir of the ref. + * + * Returns: (transfer none): the deploy dir + */ +const char * +flatpak_installed_ref_get_deploy_dir (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->deploy_dir; +} + +/** + * flatpak_installed_ref_get_is_current: + * @self: a #FlatpakInstalledRef + * + * Returns whether the ref is current. + * + * Returns: %TRUE if the ref is current + */ +gboolean +flatpak_installed_ref_get_is_current (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->is_current; +} + +/** + * flatpak_installed_ref_get_subpaths: + * @self: a #FlatpakInstalledRef + * + * Returns the subpaths that are installed, or %NULL if all files installed. + * + * Returns: (transfer none): A strv, or %NULL + */ +const char * const * +flatpak_installed_ref_get_subpaths (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return (const char * const *) priv->subpaths; +} + +/** + * flatpak_installed_ref_get_installed_size: + * @self: a #FlatpakInstalledRef + * + * Returns the installed size of the ref. + * + * Returns: the installed size + */ +guint64 +flatpak_installed_ref_get_installed_size (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->installed_size; +} + +/** + * flatpak_installed_ref_load_metadata: + * @self: a #FlatpakInstalledRef + * @cancellable: (nullable): a #GCancellable + * @error: a return location for a #GError + * + * Loads the metadata file for this ref. + * + * Returns: (transfer full): a #GBytes containing the metadata file, + * or %NULL if an error occurred + */ +GBytes * +flatpak_installed_ref_load_metadata (FlatpakInstalledRef *self, + GCancellable *cancellable, + GError **error) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + g_autofree char *path = NULL; + char *metadata; + gsize length; + + if (priv->deploy_dir == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Unknown deploy directory"); + return NULL; + } + + path = g_build_filename (priv->deploy_dir, "metadata", NULL); + if (!g_file_get_contents (path, &metadata, &length, error)) + return NULL; + + return g_bytes_new_take (metadata, length); +} + +/** + * flatpak_installed_ref_get_eol: + * @self: a #FlatpakInstalledRef + * + * Returns the end-of-life reason string, or %NULL if the + * ref is not end-of-lifed. + * + * Returns: (transfer none): the end-of-life reason or %NULL + */ +const char * +flatpak_installed_ref_get_eol (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->eol; +} + +/** + * flatpak_installed_ref_get_eol_rebase: + * @self: a #FlatpakInstalledRef + * + * Returns the end-of-life rebased ref, or %NULL if the + * ref is not end-of-lifed. + * + * Returns: (transfer none): the end-of-life rebased ref or %NULL + */ +const char * +flatpak_installed_ref_get_eol_rebase (FlatpakInstalledRef *self) +{ + FlatpakInstalledRefPrivate *priv = flatpak_installed_ref_get_instance_private (self); + + return priv->eol_rebase; +} + +FlatpakInstalledRef * +flatpak_installed_ref_new (const char *full_ref, + const char *commit, + const char *latest_commit, + const char *origin, + const char **subpaths, + const char *deploy_dir, + guint64 installed_size, + gboolean is_current, + const char *eol, + const char *eol_rebase) +{ + FlatpakRefKind kind = FLATPAK_REF_KIND_APP; + FlatpakInstalledRef *ref; + + g_auto(GStrv) parts = NULL; + + parts = g_strsplit (full_ref, "/", -1); + + if (strcmp (parts[0], "app") != 0) + kind = FLATPAK_REF_KIND_RUNTIME; + + /* Canonicalize the "no subpaths" case */ + if (subpaths && *subpaths == NULL) + subpaths = NULL; + + ref = g_object_new (FLATPAK_TYPE_INSTALLED_REF, + "kind", kind, + "name", parts[1], + "arch", parts[2], + "branch", parts[3], + "commit", commit, + "latest-commit", latest_commit, + "origin", origin, + "subpaths", subpaths, + "is-current", is_current, + "installed-size", installed_size, + "deploy-dir", deploy_dir, + "end-of-life", eol, + "end-of-life-rebase", eol_rebase, + NULL); + + return ref; +} diff -Nru flatpak-0.11.7/common/flatpak-installed-ref.h flatpak-0.11.8.3/common/flatpak-installed-ref.h --- flatpak-0.11.7/common/flatpak-installed-ref.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installed-ref.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_INSTALLED_REF_H__ +#define __FLATPAK_INSTALLED_REF_H__ + +typedef struct _FlatpakInstalledRef FlatpakInstalledRef; + +#include +#include + +#define FLATPAK_TYPE_INSTALLED_REF flatpak_installed_ref_get_type () +#define FLATPAK_INSTALLED_REF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_INSTALLED_REF, FlatpakInstalledRef)) +#define FLATPAK_IS_INSTALLED_REF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_INSTALLED_REF)) + +FLATPAK_EXTERN GType flatpak_installed_ref_get_type (void); + +struct _FlatpakInstalledRef +{ + FlatpakRef parent; +}; + +typedef struct +{ + FlatpakRefClass parent_class; +} FlatpakInstalledRefClass; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakInstalledRef, g_object_unref) +#endif + +FLATPAK_EXTERN const char *flatpak_installed_ref_get_origin (FlatpakInstalledRef * self); +FLATPAK_EXTERN const char * const *flatpak_installed_ref_get_subpaths (FlatpakInstalledRef *self); +FLATPAK_EXTERN guint64 flatpak_installed_ref_get_installed_size (FlatpakInstalledRef *self); +FLATPAK_EXTERN const char *flatpak_installed_ref_get_deploy_dir (FlatpakInstalledRef *self); +FLATPAK_EXTERN const char *flatpak_installed_ref_get_latest_commit (FlatpakInstalledRef *self); +FLATPAK_EXTERN gboolean flatpak_installed_ref_get_is_current (FlatpakInstalledRef *self); +FLATPAK_EXTERN GBytes *flatpak_installed_ref_load_metadata (FlatpakInstalledRef *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN const char * flatpak_installed_ref_get_eol (FlatpakInstalledRef *self); +FLATPAK_EXTERN const char * flatpak_installed_ref_get_eol_rebase (FlatpakInstalledRef *self); + +#endif /* __FLATPAK_INSTALLED_REF_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-installed-ref-private.h flatpak-0.11.8.3/common/flatpak-installed-ref-private.h --- flatpak-0.11.7/common/flatpak-installed-ref-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-installed-ref-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_INSTALLED_REF_PRIVATE_H__ +#define __FLATPAK_INSTALLED_REF_PRIVATE_H__ + +#include +#include + +FlatpakInstalledRef *flatpak_installed_ref_new (const char *full_ref, + const char *commit, + const char *latest_commit, + const char *origin, + const char **subpaths, + const char *deploy_dir, + guint64 installed_size, + gboolean current, + const char *eol, + const char *eol_rebase); + +#endif /* __FLATPAK_INSTALLED_REF_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-json.c flatpak-0.11.8.3/common/flatpak-json.c --- flatpak-0.11.7/common/flatpak-json.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json.c 2018-05-30 13:58:57.000000000 +0100 @@ -21,8 +21,8 @@ #include "config.h" #include "string.h" -#include "flatpak-json.h" -#include "flatpak-utils.h" +#include "flatpak-json-private.h" +#include "flatpak-utils-private.h" #include "libglnx.h" G_DEFINE_TYPE (FlatpakJson, flatpak_json, G_TYPE_OBJECT); diff -Nru flatpak-0.11.7/common/flatpak-json.h flatpak-0.11.8.3/common/flatpak-json.h --- flatpak-0.11.7/common/flatpak-json.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,109 +0,0 @@ -/* - * Copyright © 2016 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_JSON_H__ -#define __FLATPAK_JSON_H__ - -#include - -G_BEGIN_DECLS - -#define FLATPAK_TYPE_JSON flatpak_json_get_type () - -typedef struct _FlatpakJsonProp FlatpakJsonProp; - -typedef enum { - FLATPAK_JSON_PROP_TYPE_PARENT, - FLATPAK_JSON_PROP_TYPE_INT64, - FLATPAK_JSON_PROP_TYPE_BOOL, - FLATPAK_JSON_PROP_TYPE_STRING, - FLATPAK_JSON_PROP_TYPE_STRUCT, - FLATPAK_JSON_PROP_TYPE_STRUCTV, - FLATPAK_JSON_PROP_TYPE_STRV, - FLATPAK_JSON_PROP_TYPE_STRMAP, - FLATPAK_JSON_PROP_TYPE_BOOLMAP, -} FlatpakJsonPropType; - -typedef enum { - FLATPAK_JSON_PROP_FLAGS_NONE = 0, - FLATPAK_JSON_PROP_FLAGS_OPTIONAL = 1<<0, - FLATPAK_JSON_PROP_FLAGS_STRICT = 1<<1, - FLATPAK_JSON_PROP_FLAGS_MANDATORY = 1<<2, -} FlatpakJsonPropFlags; - - -struct _FlatpakJsonProp { - const char *name; - gsize offset; - FlatpakJsonPropType type; - gpointer type_data; - gpointer type_data2; - FlatpakJsonPropFlags flags; -} ; - -#define FLATPAK_JSON_STRING_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING } -#define FLATPAK_JSON_MANDATORY_STRING_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING, 0, 0, FLATPAK_JSON_PROP_FLAGS_MANDATORY } -#define FLATPAK_JSON_INT64_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_INT64 } -#define FLATPAK_JSON_BOOL_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOL } -#define FLATPAK_JSON_STRV_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRV } -#define FLATPAK_JSON_STRMAP_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRMAP } -#define FLATPAK_JSON_BOOLMAP_PROP(_struct, _field, _name) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOLMAP } -#define FLATPAK_JSON_STRUCT_PROP(_struct, _field, _name, _props) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props} -#define FLATPAK_JSON_OPT_STRUCT_PROP(_struct, _field, _name, _props) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_OPTIONAL} -#define FLATPAK_JSON_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT} -#define FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT | FLATPAK_JSON_PROP_FLAGS_MANDATORY} -#define FLATPAK_JSON_PARENT_PROP(_struct, _field, _props) \ - { "parent", G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_PARENT, (gpointer)_props} -#define FLATPAK_JSON_STRUCTV_PROP(_struct, _field, _name, _props) \ - { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCTV, (gpointer)_props, (gpointer) sizeof (**((_struct *) 0)->_field) } -#define FLATPAK_JSON_LAST_PROP { NULL } - -G_DECLARE_DERIVABLE_TYPE (FlatpakJson, flatpak_json, FLATPAK, JSON, GObject) - -struct _FlatpakJsonClass { - GObjectClass parent_class; - - FlatpakJsonProp *props; - const char *mediatype; -}; - -FlatpakJson *flatpak_json_from_node (JsonNode *node, - GType type, - GError **error); -JsonNode *flatpak_json_to_node (FlatpakJson *self); -FlatpakJson *flatpak_json_from_bytes (GBytes *bytes, - GType type, - GError **error); -GBytes *flatpak_json_to_bytes (FlatpakJson *self); - -G_END_DECLS - -#endif /* __FLATPAK_JSON_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-json-oci.c flatpak-0.11.8.3/common/flatpak-json-oci.c --- flatpak-0.11.7/common/flatpak-json-oci.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json-oci.c 2018-05-30 13:58:57.000000000 +0100 @@ -21,8 +21,8 @@ #include "config.h" #include "string.h" -#include "flatpak-json-oci.h" -#include "flatpak-utils.h" +#include "flatpak-json-oci-private.h" +#include "flatpak-utils-private.h" #include "libglnx.h" const char * diff -Nru flatpak-0.11.7/common/flatpak-json-oci.h flatpak-0.11.8.3/common/flatpak-json-oci.h --- flatpak-0.11.7/common/flatpak-json-oci.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json-oci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,318 +0,0 @@ -/* - * Copyright © 2016 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_JSON_OCI_H__ -#define __FLATPAK_JSON_OCI_H__ - -#include "flatpak-json.h" - -G_BEGIN_DECLS - -#define FLATPAK_OCI_MEDIA_TYPE_DESCRIPTOR "application/vnd.oci.descriptor.v1+json" -#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST "application/vnd.oci.image.manifest.v1+json" -#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX "application/vnd.oci.image.index.v1+json" -#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER "application/vnd.oci.image.layer.v1.tar+gzip" -#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER_NONDISTRIBUTABLE "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" -#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG "application/vnd.oci.image.config.v1+json" - -#define FLATPAK_OCI_SIGNATURE_TYPE_FLATPAK "flatpak oci image signature" - -const char * flatpak_arch_to_oci_arch (const char *flatpak_arch); -void flatpak_oci_export_annotations (GHashTable *source, - GHashTable *dest); -void flatpak_oci_copy_annotations (GHashTable *source, - GHashTable *dest); - -typedef struct { - char *mediatype; - char *digest; - gint64 size; - char **urls; - GHashTable *annotations; -} FlatpakOciDescriptor; - -FlatpakOciDescriptor *flatpak_oci_descriptor_new (const char *mediatype, - const char *digest, - gint64 size); -void flatpak_oci_descriptor_copy (FlatpakOciDescriptor *source, - FlatpakOciDescriptor *dest); -void flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self); -void flatpak_oci_descriptor_free (FlatpakOciDescriptor *self); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciDescriptor, flatpak_oci_descriptor_free) - -typedef struct -{ - char *architecture; - char *os; - char *os_version; - char **os_features; - char *variant; - char **features; -} FlatpakOciManifestPlatform; - -typedef struct -{ - FlatpakOciDescriptor parent; - FlatpakOciManifestPlatform platform; -} FlatpakOciManifestDescriptor; - -FlatpakOciManifestDescriptor * flatpak_oci_manifest_descriptor_new (void); -const char * flatpak_oci_manifest_descriptor_get_ref (FlatpakOciManifestDescriptor *m); -void flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self); -void flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self); - - -#define FLATPAK_TYPE_OCI_VERSIONED flatpak_oci_versioned_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_OCI, VERSIONED, FlatpakJson) - -struct _FlatpakOciVersioned { - FlatpakJson parent; - - int version; - char *mediatype; -}; - -struct _FlatpakOciVersionedClass { - FlatpakJsonClass parent_class; -}; - -FlatpakOciVersioned *flatpak_oci_versioned_from_json (GBytes *bytes, - GError **error); -const char * flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self); -gint64 flatpak_oci_versioned_get_version (FlatpakOciVersioned *self); - -#define FLATPAK_TYPE_OCI_MANIFEST flatpak_oci_manifest_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK, OCI_MANIFEST, FlatpakOciVersioned) - -struct _FlatpakOciManifest -{ - FlatpakOciVersioned parent; - - FlatpakOciDescriptor config; - FlatpakOciDescriptor **layers; - GHashTable *annotations; -}; - -struct _FlatpakOciManifestClass -{ - FlatpakOciVersionedClass parent_class; -}; - - -FlatpakOciManifest *flatpak_oci_manifest_new (void); -void flatpak_oci_manifest_set_config (FlatpakOciManifest *self, - FlatpakOciDescriptor *desc); -void flatpak_oci_manifest_set_layers (FlatpakOciManifest *self, - FlatpakOciDescriptor **descs); -void flatpak_oci_manifest_set_layer (FlatpakOciManifest *self, - FlatpakOciDescriptor *desc); -int flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self); -const char * flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self, - int i); -GHashTable * flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self); - -#define FLATPAK_TYPE_OCI_INDEX flatpak_oci_index_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciIndex, flatpak_oci_index, FLATPAK, OCI_INDEX, FlatpakOciVersioned) - -struct _FlatpakOciIndex -{ - FlatpakOciVersioned parent; - - FlatpakOciManifestDescriptor **manifests; - GHashTable *annotations; -}; - -struct _FlatpakOciIndexClass -{ - FlatpakOciVersionedClass parent_class; -}; - -FlatpakOciIndex * flatpak_oci_index_new (void); -void flatpak_oci_index_add_manifest (FlatpakOciIndex *self, - FlatpakOciDescriptor *desc); -gboolean flatpak_oci_index_remove_manifest (FlatpakOciIndex *self, - const char *ref); -FlatpakOciManifestDescriptor *flatpak_oci_index_get_manifest (FlatpakOciIndex *self, - const char *ref); -FlatpakOciManifestDescriptor *flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self); -int flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self); - -#define FLATPAK_TYPE_OCI_IMAGE flatpak_oci_image_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK, OCI_IMAGE, FlatpakJson) - -typedef struct -{ - char *type; - char **diff_ids; -} FlatpakOciImageRootfs; - -typedef struct -{ - char *user; - char *working_dir; - gint64 memory; - gint64 memory_swap; - gint64 cpu_shares; - char **env; - char **cmd; - char **entrypoint; - char **exposed_ports; - char **volumes; - GHashTable *labels; -} FlatpakOciImageConfig; - -typedef struct -{ - char *created; - char *created_by; - char *author; - char *comment; - gboolean empty_layer; -} FlatpakOciImageHistory; - -struct _FlatpakOciImage -{ - FlatpakJson parent; - - char *created; - char *author; - char *architecture; - char *os; - FlatpakOciImageRootfs rootfs; - FlatpakOciImageConfig config; - FlatpakOciImageHistory **history; -}; - -struct _FlatpakOciImageClass -{ - FlatpakJsonClass parent_class; -}; - -FlatpakOciImage *flatpak_oci_image_new (void); -void flatpak_oci_image_set_created (FlatpakOciImage *image, - const char *created); -void flatpak_oci_image_set_architecture (FlatpakOciImage *image, - const char *arch); -void flatpak_oci_image_set_os (FlatpakOciImage *image, - const char *os); -void flatpak_oci_image_set_layers (FlatpakOciImage *image, - const char **layers); -void flatpak_oci_image_set_layer (FlatpakOciImage *image, - const char *layer); - -void flatpak_oci_add_annotations_for_commit (GHashTable *annotations, - const char *ref, - const char *commit, - GVariant *commit_data); -void flatpak_oci_parse_commit_annotations (GHashTable *annotations, - guint64 *out_timestamp, - char **out_subject, - char **out_body, - char **out_ref, - char **out_commit, - char **out_parent_commit, - GVariantBuilder *metadata_builder); - -#define FLATPAK_TYPE_OCI_SIGNATURE flatpak_oci_signature_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK, OCI_SIGNATURE, FlatpakJson) - -typedef struct -{ - char *digest; -} FlatpakOciSignatureCriticalImage; - -typedef struct -{ - char *ref; -} FlatpakOciSignatureCriticalIdentity; - -typedef struct -{ - char *type; - FlatpakOciSignatureCriticalImage image; - FlatpakOciSignatureCriticalIdentity identity; -} FlatpakOciSignatureCritical; - -typedef struct -{ - char *creator; - gint64 timestamp; -} FlatpakOciSignatureOptional; - -struct _FlatpakOciSignature -{ - FlatpakJson parent; - - FlatpakOciSignatureCritical critical; - FlatpakOciSignatureOptional optional; -}; - -struct _FlatpakOciSignatureClass -{ - FlatpakJsonClass parent_class; -}; - -FlatpakOciSignature *flatpak_oci_signature_new (const char *digest, const char *ref); - - -#define FLATPAK_TYPE_OCI_INDEX_RESPONSE flatpak_oci_index_response_get_type () -G_DECLARE_FINAL_TYPE (FlatpakOciIndexResponse, flatpak_oci_index_response, FLATPAK, OCI_INDEX_RESPONSE, FlatpakJson) - -typedef struct -{ - char *digest; - char *mediatype; - char *os; - char *architecture; - GHashTable *annotations; - GHashTable *labels; - char **tags; -} FlatpakOciIndexImage; - -typedef struct -{ - char *digest; - char *mediatype; - char **tags; - FlatpakOciIndexImage **images; -} FlatpakOciIndexImageList; - -typedef struct -{ - char *name; - FlatpakOciIndexImage **images; - FlatpakOciIndexImageList **lists; -} FlatpakOciIndexRepository; - -struct _FlatpakOciIndexResponse -{ - FlatpakJson parent; - - char *registry; - FlatpakOciIndexRepository **results; -}; - -struct _FlatpakOciIndexResponseClass -{ - FlatpakJsonClass parent_class; -}; - -#endif /* __FLATPAK_JSON_OCI_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-json-oci-private.h flatpak-0.11.8.3/common/flatpak-json-oci-private.h --- flatpak-0.11.7/common/flatpak-json-oci-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json-oci-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,318 @@ +/* + * Copyright © 2016 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_JSON_OCI_H__ +#define __FLATPAK_JSON_OCI_H__ + +#include "flatpak-json-private.h" + +G_BEGIN_DECLS + +#define FLATPAK_OCI_MEDIA_TYPE_DESCRIPTOR "application/vnd.oci.descriptor.v1+json" +#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST "application/vnd.oci.image.manifest.v1+json" +#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX "application/vnd.oci.image.index.v1+json" +#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER "application/vnd.oci.image.layer.v1.tar+gzip" +#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER_NONDISTRIBUTABLE "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" +#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG "application/vnd.oci.image.config.v1+json" + +#define FLATPAK_OCI_SIGNATURE_TYPE_FLATPAK "flatpak oci image signature" + +const char * flatpak_arch_to_oci_arch (const char *flatpak_arch); +void flatpak_oci_export_annotations (GHashTable *source, + GHashTable *dest); +void flatpak_oci_copy_annotations (GHashTable *source, + GHashTable *dest); + +typedef struct { + char *mediatype; + char *digest; + gint64 size; + char **urls; + GHashTable *annotations; +} FlatpakOciDescriptor; + +FlatpakOciDescriptor *flatpak_oci_descriptor_new (const char *mediatype, + const char *digest, + gint64 size); +void flatpak_oci_descriptor_copy (FlatpakOciDescriptor *source, + FlatpakOciDescriptor *dest); +void flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self); +void flatpak_oci_descriptor_free (FlatpakOciDescriptor *self); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciDescriptor, flatpak_oci_descriptor_free) + +typedef struct +{ + char *architecture; + char *os; + char *os_version; + char **os_features; + char *variant; + char **features; +} FlatpakOciManifestPlatform; + +typedef struct +{ + FlatpakOciDescriptor parent; + FlatpakOciManifestPlatform platform; +} FlatpakOciManifestDescriptor; + +FlatpakOciManifestDescriptor * flatpak_oci_manifest_descriptor_new (void); +const char * flatpak_oci_manifest_descriptor_get_ref (FlatpakOciManifestDescriptor *m); +void flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self); +void flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self); + + +#define FLATPAK_TYPE_OCI_VERSIONED flatpak_oci_versioned_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_OCI, VERSIONED, FlatpakJson) + +struct _FlatpakOciVersioned { + FlatpakJson parent; + + int version; + char *mediatype; +}; + +struct _FlatpakOciVersionedClass { + FlatpakJsonClass parent_class; +}; + +FlatpakOciVersioned *flatpak_oci_versioned_from_json (GBytes *bytes, + GError **error); +const char * flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self); +gint64 flatpak_oci_versioned_get_version (FlatpakOciVersioned *self); + +#define FLATPAK_TYPE_OCI_MANIFEST flatpak_oci_manifest_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK, OCI_MANIFEST, FlatpakOciVersioned) + +struct _FlatpakOciManifest +{ + FlatpakOciVersioned parent; + + FlatpakOciDescriptor config; + FlatpakOciDescriptor **layers; + GHashTable *annotations; +}; + +struct _FlatpakOciManifestClass +{ + FlatpakOciVersionedClass parent_class; +}; + + +FlatpakOciManifest *flatpak_oci_manifest_new (void); +void flatpak_oci_manifest_set_config (FlatpakOciManifest *self, + FlatpakOciDescriptor *desc); +void flatpak_oci_manifest_set_layers (FlatpakOciManifest *self, + FlatpakOciDescriptor **descs); +void flatpak_oci_manifest_set_layer (FlatpakOciManifest *self, + FlatpakOciDescriptor *desc); +int flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self); +const char * flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self, + int i); +GHashTable * flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self); + +#define FLATPAK_TYPE_OCI_INDEX flatpak_oci_index_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciIndex, flatpak_oci_index, FLATPAK, OCI_INDEX, FlatpakOciVersioned) + +struct _FlatpakOciIndex +{ + FlatpakOciVersioned parent; + + FlatpakOciManifestDescriptor **manifests; + GHashTable *annotations; +}; + +struct _FlatpakOciIndexClass +{ + FlatpakOciVersionedClass parent_class; +}; + +FlatpakOciIndex * flatpak_oci_index_new (void); +void flatpak_oci_index_add_manifest (FlatpakOciIndex *self, + FlatpakOciDescriptor *desc); +gboolean flatpak_oci_index_remove_manifest (FlatpakOciIndex *self, + const char *ref); +FlatpakOciManifestDescriptor *flatpak_oci_index_get_manifest (FlatpakOciIndex *self, + const char *ref); +FlatpakOciManifestDescriptor *flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self); +int flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self); + +#define FLATPAK_TYPE_OCI_IMAGE flatpak_oci_image_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK, OCI_IMAGE, FlatpakJson) + +typedef struct +{ + char *type; + char **diff_ids; +} FlatpakOciImageRootfs; + +typedef struct +{ + char *user; + char *working_dir; + gint64 memory; + gint64 memory_swap; + gint64 cpu_shares; + char **env; + char **cmd; + char **entrypoint; + char **exposed_ports; + char **volumes; + GHashTable *labels; +} FlatpakOciImageConfig; + +typedef struct +{ + char *created; + char *created_by; + char *author; + char *comment; + gboolean empty_layer; +} FlatpakOciImageHistory; + +struct _FlatpakOciImage +{ + FlatpakJson parent; + + char *created; + char *author; + char *architecture; + char *os; + FlatpakOciImageRootfs rootfs; + FlatpakOciImageConfig config; + FlatpakOciImageHistory **history; +}; + +struct _FlatpakOciImageClass +{ + FlatpakJsonClass parent_class; +}; + +FlatpakOciImage *flatpak_oci_image_new (void); +void flatpak_oci_image_set_created (FlatpakOciImage *image, + const char *created); +void flatpak_oci_image_set_architecture (FlatpakOciImage *image, + const char *arch); +void flatpak_oci_image_set_os (FlatpakOciImage *image, + const char *os); +void flatpak_oci_image_set_layers (FlatpakOciImage *image, + const char **layers); +void flatpak_oci_image_set_layer (FlatpakOciImage *image, + const char *layer); + +void flatpak_oci_add_annotations_for_commit (GHashTable *annotations, + const char *ref, + const char *commit, + GVariant *commit_data); +void flatpak_oci_parse_commit_annotations (GHashTable *annotations, + guint64 *out_timestamp, + char **out_subject, + char **out_body, + char **out_ref, + char **out_commit, + char **out_parent_commit, + GVariantBuilder *metadata_builder); + +#define FLATPAK_TYPE_OCI_SIGNATURE flatpak_oci_signature_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK, OCI_SIGNATURE, FlatpakJson) + +typedef struct +{ + char *digest; +} FlatpakOciSignatureCriticalImage; + +typedef struct +{ + char *ref; +} FlatpakOciSignatureCriticalIdentity; + +typedef struct +{ + char *type; + FlatpakOciSignatureCriticalImage image; + FlatpakOciSignatureCriticalIdentity identity; +} FlatpakOciSignatureCritical; + +typedef struct +{ + char *creator; + gint64 timestamp; +} FlatpakOciSignatureOptional; + +struct _FlatpakOciSignature +{ + FlatpakJson parent; + + FlatpakOciSignatureCritical critical; + FlatpakOciSignatureOptional optional; +}; + +struct _FlatpakOciSignatureClass +{ + FlatpakJsonClass parent_class; +}; + +FlatpakOciSignature *flatpak_oci_signature_new (const char *digest, const char *ref); + + +#define FLATPAK_TYPE_OCI_INDEX_RESPONSE flatpak_oci_index_response_get_type () +G_DECLARE_FINAL_TYPE (FlatpakOciIndexResponse, flatpak_oci_index_response, FLATPAK, OCI_INDEX_RESPONSE, FlatpakJson) + +typedef struct +{ + char *digest; + char *mediatype; + char *os; + char *architecture; + GHashTable *annotations; + GHashTable *labels; + char **tags; +} FlatpakOciIndexImage; + +typedef struct +{ + char *digest; + char *mediatype; + char **tags; + FlatpakOciIndexImage **images; +} FlatpakOciIndexImageList; + +typedef struct +{ + char *name; + FlatpakOciIndexImage **images; + FlatpakOciIndexImageList **lists; +} FlatpakOciIndexRepository; + +struct _FlatpakOciIndexResponse +{ + FlatpakJson parent; + + char *registry; + FlatpakOciIndexRepository **results; +}; + +struct _FlatpakOciIndexResponseClass +{ + FlatpakJsonClass parent_class; +}; + +#endif /* __FLATPAK_JSON_OCI_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-json-private.h flatpak-0.11.8.3/common/flatpak-json-private.h --- flatpak-0.11.7/common/flatpak-json-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-json-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,109 @@ +/* + * Copyright © 2016 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_JSON_H__ +#define __FLATPAK_JSON_H__ + +#include + +G_BEGIN_DECLS + +#define FLATPAK_TYPE_JSON flatpak_json_get_type () + +typedef struct _FlatpakJsonProp FlatpakJsonProp; + +typedef enum { + FLATPAK_JSON_PROP_TYPE_PARENT, + FLATPAK_JSON_PROP_TYPE_INT64, + FLATPAK_JSON_PROP_TYPE_BOOL, + FLATPAK_JSON_PROP_TYPE_STRING, + FLATPAK_JSON_PROP_TYPE_STRUCT, + FLATPAK_JSON_PROP_TYPE_STRUCTV, + FLATPAK_JSON_PROP_TYPE_STRV, + FLATPAK_JSON_PROP_TYPE_STRMAP, + FLATPAK_JSON_PROP_TYPE_BOOLMAP, +} FlatpakJsonPropType; + +typedef enum { + FLATPAK_JSON_PROP_FLAGS_NONE = 0, + FLATPAK_JSON_PROP_FLAGS_OPTIONAL = 1<<0, + FLATPAK_JSON_PROP_FLAGS_STRICT = 1<<1, + FLATPAK_JSON_PROP_FLAGS_MANDATORY = 1<<2, +} FlatpakJsonPropFlags; + + +struct _FlatpakJsonProp { + const char *name; + gsize offset; + FlatpakJsonPropType type; + gpointer type_data; + gpointer type_data2; + FlatpakJsonPropFlags flags; +} ; + +#define FLATPAK_JSON_STRING_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING } +#define FLATPAK_JSON_MANDATORY_STRING_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING, 0, 0, FLATPAK_JSON_PROP_FLAGS_MANDATORY } +#define FLATPAK_JSON_INT64_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_INT64 } +#define FLATPAK_JSON_BOOL_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOL } +#define FLATPAK_JSON_STRV_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRV } +#define FLATPAK_JSON_STRMAP_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRMAP } +#define FLATPAK_JSON_BOOLMAP_PROP(_struct, _field, _name) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOLMAP } +#define FLATPAK_JSON_STRUCT_PROP(_struct, _field, _name, _props) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props} +#define FLATPAK_JSON_OPT_STRUCT_PROP(_struct, _field, _name, _props) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_OPTIONAL} +#define FLATPAK_JSON_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT} +#define FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT | FLATPAK_JSON_PROP_FLAGS_MANDATORY} +#define FLATPAK_JSON_PARENT_PROP(_struct, _field, _props) \ + { "parent", G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_PARENT, (gpointer)_props} +#define FLATPAK_JSON_STRUCTV_PROP(_struct, _field, _name, _props) \ + { _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCTV, (gpointer)_props, (gpointer) sizeof (**((_struct *) 0)->_field) } +#define FLATPAK_JSON_LAST_PROP { NULL } + +G_DECLARE_DERIVABLE_TYPE (FlatpakJson, flatpak_json, FLATPAK, JSON, GObject) + +struct _FlatpakJsonClass { + GObjectClass parent_class; + + FlatpakJsonProp *props; + const char *mediatype; +}; + +FlatpakJson *flatpak_json_from_node (JsonNode *node, + GType type, + GError **error); +JsonNode *flatpak_json_to_node (FlatpakJson *self); +FlatpakJson *flatpak_json_from_bytes (GBytes *bytes, + GType type, + GError **error); +GBytes *flatpak_json_to_bytes (FlatpakJson *self); + +G_END_DECLS + +#endif /* __FLATPAK_JSON_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-oci-registry.c flatpak-0.11.8.3/common/flatpak-oci-registry.c --- flatpak-0.11.7/common/flatpak-oci-registry.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-oci-registry.c 2018-05-30 13:58:57.000000000 +0100 @@ -28,8 +28,8 @@ #include #include -#include "flatpak-oci-registry.h" -#include "flatpak-utils.h" +#include "flatpak-oci-registry-private.h" +#include "flatpak-utils-private.h" G_DEFINE_QUARK (flatpak_oci_error, flatpak_oci_error) @@ -1882,7 +1882,7 @@ if (json == NULL) return FALSE; - return g_steal_pointer (&json); + return (FlatpakOciSignature *)g_steal_pointer (&json); } static const char * @@ -2143,5 +2143,5 @@ } } - return flatpak_fail (error, "No matching image for %s\n", ref); + return flatpak_fail (error, "No matching image for %s", ref); } diff -Nru flatpak-0.11.7/common/flatpak-oci-registry.h flatpak-0.11.8.3/common/flatpak-oci-registry.h --- flatpak-0.11.7/common/flatpak-oci-registry.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-oci-registry.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,149 +0,0 @@ -/* - * Copyright © 2016 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_OCI_REGISTRY_H__ -#define __FLATPAK_OCI_REGISTRY_H__ - -#include "libglnx/libglnx.h" - -#include -#include -#include -#include "flatpak-json-oci.h" -#include "flatpak-utils.h" - -#define FLATPAK_TYPE_OCI_REGISTRY flatpak_oci_registry_get_type () -#define FLATPAK_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_REGISTRY, FlatpakOciRegistry)) -#define FLATPAK_IS_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_REGISTRY)) - -GType flatpak_oci_registry_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciRegistry, g_object_unref) - -#define FLATPAK_TYPE_OCI_LAYER_WRITER flatpak_oci_layer_writer_get_type () -#define FLATPAK_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER, FlatpakOciLayerWriter)) -#define FLATPAK_IS_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER)) - -GType flatpak_oci_layer_writer_get_type (void); - -typedef enum { - FLATPAK_OCI_ERROR_NOT_CHANGED = 0, -} FlatpakOciErrorEnum; - -#define FLATPAK_OCI_ERROR flatpak_oci_error_quark () - -FLATPAK_EXTERN GQuark flatpak_oci_error_quark (void); - -typedef struct FlatpakOciLayerWriter FlatpakOciLayerWriter; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciLayerWriter, g_object_unref) - -FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri, - gboolean for_write, - int tmp_dfd, - GCancellable *cancellable, - GError **error); -const char * flatpak_oci_registry_get_uri (FlatpakOciRegistry *self); -FlatpakOciIndex * flatpak_oci_registry_load_index (FlatpakOciRegistry *self, - const char *etag, - char **etag_out, - GCancellable *cancellable, - GError **error); -gboolean flatpak_oci_registry_save_index (FlatpakOciRegistry *self, - FlatpakOciIndex *index, - GCancellable *cancellable, - GError **error); -int flatpak_oci_registry_download_blob (FlatpakOciRegistry *self, - const char *repository, - gboolean manifest, - const char *digest, - FlatpakLoadUriProgress progress_cb, - gpointer user_data, - GCancellable *cancellable, - GError **error); -GBytes * flatpak_oci_registry_load_blob (FlatpakOciRegistry *self, - const char *repository, - gboolean manifest, - const char *digest, - GCancellable *cancellable, - GError **error); -char * flatpak_oci_registry_store_blob (FlatpakOciRegistry *self, - GBytes *data, - GCancellable *cancellable, - GError **error); -gboolean flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self, - FlatpakOciRegistry *source_registry, - const char *repository, - gboolean manifest, - const char *digest, - FlatpakLoadUriProgress progress_cb, - gpointer user_data, - GCancellable *cancellable, - GError **error); -FlatpakOciDescriptor * flatpak_oci_registry_store_json (FlatpakOciRegistry *self, - FlatpakJson *json, - GCancellable *cancellable, - GError **error); -FlatpakOciVersioned * flatpak_oci_registry_load_versioned (FlatpakOciRegistry *self, - const char *repository, - const char *digest, - gsize *out_size, - GCancellable *cancellable, - GError **error); -FlatpakOciLayerWriter *flatpak_oci_registry_write_layer (FlatpakOciRegistry *self, - GCancellable *cancellable, - GError **error); - -struct archive *flatpak_oci_layer_writer_get_archive (FlatpakOciLayerWriter *self); -gboolean flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self, - char **uncompressed_digest_out, - FlatpakOciDescriptor **res_out, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_archive_read_open_fd_with_checksum (struct archive *a, - int fd, - GChecksum *checksum, - GError **error); - -GBytes *flatpak_oci_sign_data (GBytes *data, - const gchar **okey_ids, - const char *homedir, - GError **error); - -FlatpakOciSignature *flatpak_oci_verify_signature (OstreeRepo *repo, - const char *remote_name, - GBytes *signature, - GError **error); - -GVariant *flatpak_oci_index_fetch_summary (SoupSession *soup_session, - const char *uri, - const char *etag, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_oci_index_verify_ref (SoupSession *soup_session, - const char *uri, - const char *ref, - const char *digest, - GCancellable *cancellable, - GError **error); - -#endif /* __FLATPAK_OCI_REGISTRY_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-oci-registry-private.h flatpak-0.11.8.3/common/flatpak-oci-registry-private.h --- flatpak-0.11.7/common/flatpak-oci-registry-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-oci-registry-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,149 @@ +/* + * Copyright © 2016 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_OCI_REGISTRY_H__ +#define __FLATPAK_OCI_REGISTRY_H__ + +#include "libglnx/libglnx.h" + +#include +#include +#include +#include "flatpak-json-oci-private.h" +#include "flatpak-utils-private.h" + +#define FLATPAK_TYPE_OCI_REGISTRY flatpak_oci_registry_get_type () +#define FLATPAK_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_REGISTRY, FlatpakOciRegistry)) +#define FLATPAK_IS_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_REGISTRY)) + +GType flatpak_oci_registry_get_type (void); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciRegistry, g_object_unref) + +#define FLATPAK_TYPE_OCI_LAYER_WRITER flatpak_oci_layer_writer_get_type () +#define FLATPAK_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER, FlatpakOciLayerWriter)) +#define FLATPAK_IS_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER)) + +GType flatpak_oci_layer_writer_get_type (void); + +typedef enum { + FLATPAK_OCI_ERROR_NOT_CHANGED = 0, +} FlatpakOciErrorEnum; + +#define FLATPAK_OCI_ERROR flatpak_oci_error_quark () + +FLATPAK_EXTERN GQuark flatpak_oci_error_quark (void); + +typedef struct FlatpakOciLayerWriter FlatpakOciLayerWriter; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciLayerWriter, g_object_unref) + +FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri, + gboolean for_write, + int tmp_dfd, + GCancellable *cancellable, + GError **error); +const char * flatpak_oci_registry_get_uri (FlatpakOciRegistry *self); +FlatpakOciIndex * flatpak_oci_registry_load_index (FlatpakOciRegistry *self, + const char *etag, + char **etag_out, + GCancellable *cancellable, + GError **error); +gboolean flatpak_oci_registry_save_index (FlatpakOciRegistry *self, + FlatpakOciIndex *index, + GCancellable *cancellable, + GError **error); +int flatpak_oci_registry_download_blob (FlatpakOciRegistry *self, + const char *repository, + gboolean manifest, + const char *digest, + FlatpakLoadUriProgress progress_cb, + gpointer user_data, + GCancellable *cancellable, + GError **error); +GBytes * flatpak_oci_registry_load_blob (FlatpakOciRegistry *self, + const char *repository, + gboolean manifest, + const char *digest, + GCancellable *cancellable, + GError **error); +char * flatpak_oci_registry_store_blob (FlatpakOciRegistry *self, + GBytes *data, + GCancellable *cancellable, + GError **error); +gboolean flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self, + FlatpakOciRegistry *source_registry, + const char *repository, + gboolean manifest, + const char *digest, + FlatpakLoadUriProgress progress_cb, + gpointer user_data, + GCancellable *cancellable, + GError **error); +FlatpakOciDescriptor * flatpak_oci_registry_store_json (FlatpakOciRegistry *self, + FlatpakJson *json, + GCancellable *cancellable, + GError **error); +FlatpakOciVersioned * flatpak_oci_registry_load_versioned (FlatpakOciRegistry *self, + const char *repository, + const char *digest, + gsize *out_size, + GCancellable *cancellable, + GError **error); +FlatpakOciLayerWriter *flatpak_oci_registry_write_layer (FlatpakOciRegistry *self, + GCancellable *cancellable, + GError **error); + +struct archive *flatpak_oci_layer_writer_get_archive (FlatpakOciLayerWriter *self); +gboolean flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self, + char **uncompressed_digest_out, + FlatpakOciDescriptor **res_out, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_archive_read_open_fd_with_checksum (struct archive *a, + int fd, + GChecksum *checksum, + GError **error); + +GBytes *flatpak_oci_sign_data (GBytes *data, + const gchar **okey_ids, + const char *homedir, + GError **error); + +FlatpakOciSignature *flatpak_oci_verify_signature (OstreeRepo *repo, + const char *remote_name, + GBytes *signature, + GError **error); + +GVariant *flatpak_oci_index_fetch_summary (SoupSession *soup_session, + const char *uri, + const char *etag, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_oci_index_verify_ref (SoupSession *soup_session, + const char *uri, + const char *ref, + const char *digest, + GCancellable *cancellable, + GError **error); + +#endif /* __FLATPAK_OCI_REGISTRY_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-portal-error.h flatpak-0.11.8.3/common/flatpak-portal-error.h --- flatpak-0.11.7/common/flatpak-portal-error.h 2018-04-04 16:31:23.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-portal-error.h 2018-05-30 13:58:57.000000000 +0100 @@ -22,12 +22,23 @@ #ifndef FLATPAK_PORTAL_ERROR_H #define FLATPAK_PORTAL_ERROR_H +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + #include G_BEGIN_DECLS /** - * XdpErrorEnum: + * FlatpakPortalError: + * @FLATPAK_PORTAL_ERROR_FAILED: General portal failure + * @FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT: An argument was invalid + * @FLATPAK_PORTAL_ERROR_NOT_FOUND: The object was not fount + * @FLATPAK_PORTAL_ERROR_EXISTS: The object already exists + * @FLATPAK_PORTAL_ERROR_NOT_ALLOWED: The call was not allowed + * @FLATPAK_PORTAL_ERROR_CANCELLED: The call was cancelled by the user + * @FLATPAK_PORTAL_ERROR_WINDOW_DESTROYED: The window was destroyed by the user */ typedef enum { FLATPAK_PORTAL_ERROR_FAILED = 0, @@ -37,7 +48,7 @@ FLATPAK_PORTAL_ERROR_NOT_ALLOWED, FLATPAK_PORTAL_ERROR_CANCELLED, FLATPAK_PORTAL_ERROR_WINDOW_DESTROYED, -} FlatpakErrorEnum; +} FlatpakPortalError; #define FLATPAK_PORTAL_ERROR flatpak_portal_error_quark () diff -Nru flatpak-0.11.7/common/flatpak-ref.c flatpak-0.11.8.3/common/flatpak-ref.c --- flatpak-0.11.7/common/flatpak-ref.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-ref.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,397 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-utils-private.h" +#include "flatpak-ref.h" +#include "flatpak-enum-types.h" + +/** + * SECTION:flatpak-ref + * @Title: FlatpakRef + * @Short_description: Application reference + * + * Currently flatpak manages two types of binary artifacts: applications, and + * runtimes. Applications contain a program that desktop users can run, while + * runtimes contain only libraries and data. An FlatpakRef object (or short: ref) + * can refer to either of these. + * + * Both applications and runtimes are identified by a 4-tuple of strings: kind, + * name, arch and branch, e.g. app/org.gnome.evince/x86_64/master. The functions + * flatpak_ref_parse() and flatpak_ref_format_ref() can be used to convert + * FlatpakRef objects into this string representation and back. + * + * To uniquely identify a particular version of an application or runtime, you + * need a commit. + * + * The subclasses #FlatpakInstalledRef and #FlatpakRemoteRef provide more information + * for artifacts that are locally installed or available from a remote repository. + */ +typedef struct _FlatpakRefPrivate FlatpakRefPrivate; + +struct _FlatpakRefPrivate +{ + char *name; + char *arch; + char *branch; + char *commit; + FlatpakRefKind kind; + char *collection_id; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakRef, flatpak_ref, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_NAME, + PROP_ARCH, + PROP_BRANCH, + PROP_COMMIT, + PROP_KIND, + PROP_COLLECTION_ID, +}; + +static void +flatpak_ref_finalize (GObject *object) +{ + FlatpakRef *self = FLATPAK_REF (object); + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + g_free (priv->name); + g_free (priv->arch); + g_free (priv->branch); + g_free (priv->commit); + + G_OBJECT_CLASS (flatpak_ref_parent_class)->finalize (object); +} + +static void +flatpak_ref_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakRef *self = FLATPAK_REF (object); + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_NAME: + g_clear_pointer (&priv->name, g_free); + priv->name = g_value_dup_string (value); + break; + + case PROP_ARCH: + g_clear_pointer (&priv->arch, g_free); + priv->arch = g_value_dup_string (value); + break; + + case PROP_BRANCH: + g_clear_pointer (&priv->branch, g_free); + priv->branch = g_value_dup_string (value); + break; + + case PROP_COMMIT: + g_clear_pointer (&priv->commit, g_free); + priv->commit = g_value_dup_string (value); + break; + + case PROP_KIND: + priv->kind = g_value_get_enum (value); + break; + + case PROP_COLLECTION_ID: + g_clear_pointer (&priv->collection_id, g_free); + priv->collection_id = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_ref_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakRef *self = FLATPAK_REF (object); + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_ARCH: + g_value_set_string (value, priv->arch); + break; + + case PROP_BRANCH: + g_value_set_string (value, priv->branch); + break; + + case PROP_COMMIT: + g_value_set_string (value, priv->commit); + break; + + case PROP_KIND: + g_value_set_enum (value, priv->kind); + break; + + case PROP_COLLECTION_ID: + g_value_set_string (value, priv->collection_id); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_ref_class_init (FlatpakRefClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_ref_get_property; + object_class->set_property = flatpak_ref_set_property; + object_class->finalize = flatpak_ref_finalize; + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Name", + "The name of the application or runtime", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_ARCH, + g_param_spec_string ("arch", + "Architecture", + "The architecture of the application or runtime", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_BRANCH, + g_param_spec_string ("branch", + "Branch", + "The branch of the application or runtime", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_COMMIT, + g_param_spec_string ("commit", + "Commit", + "The commit", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_KIND, + g_param_spec_enum ("kind", + "Kind", + "The kind of artifact", + FLATPAK_TYPE_REF_KIND, + FLATPAK_REF_KIND_APP, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_COLLECTION_ID, + g_param_spec_string ("collection-id", + "Collection ID", + "The collection ID", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); +} + +static void +flatpak_ref_init (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + priv->kind = FLATPAK_REF_KIND_APP; +} + +/** + * flatpak_ref_get_name: + * @self: a #FlatpakRef + * + * Gets the name of the ref. + * + * Returns: (transfer none): the name + */ +const char * +flatpak_ref_get_name (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->name; +} + +/** + * flatpak_ref_get_arch: + * @self: a #FlatpakRef + * + * Gets the arch or the ref. + * + * Returns: (transfer none): the arch + */ +const char * +flatpak_ref_get_arch (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->arch; +} + +/** + * flatpak_ref_get_branch: + * @self: a #FlatpakRef + * + * Gets the branch of the ref. + * + * Returns: (transfer none): the branch + */ +const char * +flatpak_ref_get_branch (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->branch; +} + +/** + * flatpak_ref_get_commit: + * @self: a #FlatpakRef + * + * Gets the commit of the ref. + * + * Returns: (transfer none): the commit + */ +const char * +flatpak_ref_get_commit (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->commit; +} + +/** + * flatpak_ref_get_kind: + * @self: a #FlatpakRef + * + * Gets the kind of artifact that this ref refers to. + * + * Returns: the kind of artifact + */ +FlatpakRefKind +flatpak_ref_get_kind (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->kind; +} + +/** + * flatpak_ref_format_ref: + * @self: a #FlatpakRef + * + * Convert an FlatpakRef object into a string representation that + * can be parsed by flatpak_ref_parse(). + * + * Returns: (transfer full): string representation + */ +char * +flatpak_ref_format_ref (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + if (priv->kind == FLATPAK_REF_KIND_APP) + return flatpak_build_app_ref (priv->name, + priv->branch, + priv->arch); + else + return flatpak_build_runtime_ref (priv->name, + priv->branch, + priv->arch); +} + +/** + * flatpak_ref_parse: + * @ref: A string ref name, such as "app/org.test.App/86_64/master" + * @error: return location for a #GError + * + * Tries to parse a full ref name and return a #FlatpakRef (without a + * commit set) or fail if the ref is invalid somehow. + * + * Returns: (transfer full): an #FlatpakRef, or %NULL + */ +FlatpakRef * +flatpak_ref_parse (const char *ref, GError **error) +{ + g_auto(GStrv) parts = NULL; + + parts = flatpak_decompose_ref (ref, error); + if (parts == NULL) + return NULL; + + FlatpakRefKind kind; + if (g_strcmp0 (parts[0], "app") == 0) + { + kind = FLATPAK_REF_KIND_APP; + } + else if (g_strcmp0 (parts[0], "runtime") == 0) + { + kind = FLATPAK_REF_KIND_RUNTIME; + } + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Invalid kind: %s", parts[0]); + return NULL; + } + + return FLATPAK_REF (g_object_new (FLATPAK_TYPE_REF, + "kind", kind, + "name", parts[1], + "arch", parts[2], + "branch", parts[3], + NULL)); +} + +/** + * flatpak_ref_get_collection_id: + * @self: a #FlatpakRef + * + * Gets the collection ID of the ref. + * + * Returns: (transfer none): the collection ID + */ +const char * +flatpak_ref_get_collection_id (FlatpakRef *self) +{ + FlatpakRefPrivate *priv = flatpak_ref_get_instance_private (self); + + return priv->collection_id; +} diff -Nru flatpak-0.11.7/common/flatpak-ref.h flatpak-0.11.8.3/common/flatpak-ref.h --- flatpak-0.11.7/common/flatpak-ref.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-ref.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_REF_H__ +#define __FLATPAK_REF_H__ + +typedef struct _FlatpakRef FlatpakRef; + +#include + +#define FLATPAK_TYPE_REF flatpak_ref_get_type () +#define FLATPAK_REF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_REF, FlatpakRef)) +#define FLATPAK_IS_REF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_REF)) + +FLATPAK_EXTERN GType flatpak_ref_get_type (void); + +struct _FlatpakRef +{ + GObject parent; +}; + +typedef struct +{ + GObjectClass parent_class; +} FlatpakRefClass; + + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRef, g_object_unref) +#endif + +/** + * FlatpakRefKind: + * @FLATPAK_REF_KIND_APP: An application + * @FLATPAK_REF_KIND_RUNTIME: A runtime that applications can use. + * + * The kind of artifact that a FlatpakRef refers to. + */ +typedef enum { + FLATPAK_REF_KIND_APP, + FLATPAK_REF_KIND_RUNTIME, +} FlatpakRefKind; + +FLATPAK_EXTERN const char * flatpak_ref_get_name (FlatpakRef *self); +FLATPAK_EXTERN const char * flatpak_ref_get_arch (FlatpakRef *self); +FLATPAK_EXTERN const char * flatpak_ref_get_branch (FlatpakRef *self); +FLATPAK_EXTERN const char * flatpak_ref_get_commit (FlatpakRef *self); +FLATPAK_EXTERN FlatpakRefKind flatpak_ref_get_kind (FlatpakRef *self); +FLATPAK_EXTERN char * flatpak_ref_format_ref (FlatpakRef *self); +FLATPAK_EXTERN FlatpakRef * flatpak_ref_parse (const char *ref, + GError **error); +FLATPAK_EXTERN const char * flatpak_ref_get_collection_id (FlatpakRef *self); + +#endif /* __FLATPAK_REF_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-related-ref.c flatpak-0.11.8.3/common/flatpak-related-ref.c --- flatpak-0.11.7/common/flatpak-related-ref.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-related-ref.c 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,295 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include + +#include "flatpak-utils-private.h" +#include "flatpak-related-ref.h" +#include "flatpak-related-ref-private.h" +#include "flatpak-enum-types.h" + +/** + * SECTION:flatpak-related-ref + * @Title: FlatpakRelatedRef + * @Short_description: Related application reference + * + * A FlatpakRelatedRef provides information about an ref that is related + * to another ref. For instance, the local extension ref of an app. + * + * Since: 0.6.7 + */ + +typedef struct _FlatpakRelatedRefPrivate FlatpakRelatedRefPrivate; + +struct _FlatpakRelatedRefPrivate +{ + char **subpaths; + gboolean download; + gboolean delete; + gboolean autoprune; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakRelatedRef, flatpak_related_ref, FLATPAK_TYPE_REF) + +enum { + PROP_0, + + PROP_SUBPATHS, + PROP_SHOULD_DOWNLOAD, + PROP_SHOULD_DELETE, + PROP_SHOULD_AUTOPRUNE, +}; + +static void +flatpak_related_ref_finalize (GObject *object) +{ + FlatpakRelatedRef *self = FLATPAK_RELATED_REF (object); + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + g_strfreev (priv->subpaths); + + G_OBJECT_CLASS (flatpak_related_ref_parent_class)->finalize (object); +} + +static void +flatpak_related_ref_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakRelatedRef *self = FLATPAK_RELATED_REF (object); + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_SHOULD_DOWNLOAD: + priv->download = g_value_get_boolean (value); + break; + + case PROP_SHOULD_DELETE: + priv->delete = g_value_get_boolean (value); + break; + + case PROP_SHOULD_AUTOPRUNE: + priv->autoprune = g_value_get_boolean (value); + break; + + case PROP_SUBPATHS: + g_clear_pointer (&priv->subpaths, g_strfreev); + priv->subpaths = g_strdupv (g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_related_ref_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakRelatedRef *self = FLATPAK_RELATED_REF (object); + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_SHOULD_DOWNLOAD: + g_value_set_boolean (value, priv->download); + break; + + case PROP_SHOULD_DELETE: + g_value_set_boolean (value, priv->delete); + break; + + case PROP_SHOULD_AUTOPRUNE: + g_value_set_boolean (value, priv->autoprune); + break; + + case PROP_SUBPATHS: + g_value_set_boxed (value, priv->subpaths); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_related_ref_class_init (FlatpakRelatedRefClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_related_ref_get_property; + object_class->set_property = flatpak_related_ref_set_property; + object_class->finalize = flatpak_related_ref_finalize; + + g_object_class_install_property (object_class, + PROP_SHOULD_DOWNLOAD, + g_param_spec_boolean ("should-download", + "Should download", + "Whether to auto-download the ref with the main ref", + FALSE, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_SHOULD_DELETE, + g_param_spec_boolean ("should-delete", + "Should delete", + "Whether to auto-delete the ref with the main ref", + FALSE, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_SHOULD_AUTOPRUNE, + g_param_spec_boolean ("should-autoprune", + "Should autoprune", + "Whether to delete when pruning unused refs", + FALSE, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_SUBPATHS, + g_param_spec_boxed ("subpaths", + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); +} + +static void +flatpak_related_ref_init (FlatpakRelatedRef *self) +{ +} + +/** + * flatpak_related_ref_get_download: + * @self: a #FlatpakRelatedRef + * + * Returns whether to auto-download the ref with the main ref. + * + * Returns: %TRUE if the ref should be downloaded with the main ref. + * + * Since: 0.6.7 +*/ +gboolean +flatpak_related_ref_should_download (FlatpakRelatedRef *self) +{ + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + return priv->download; +} + +/** + * flatpak_related_ref_should_delete: + * @self: a #FlatpakRelatedRef + * + * Returns whether to auto-delete the ref with the main ref. + * + * Returns: %TRUE if the ref should be deleted with the main ref. + * + * Since: 0.6.7 + */ +gboolean +flatpak_related_ref_should_delete (FlatpakRelatedRef *self) +{ + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + return priv->delete; +} + +/** + * flatpak_related_ref_should_autoprune: + * @self: a #FlatpakRelatedRef + * + * Returns whether to delete when pruning unused refs. + * + * Returns: %TRUE if the ref should be considered unused when pruning. + * + * Since: 0.11.8 + */ +gboolean +flatpak_related_ref_should_autoprune (FlatpakRelatedRef *self) +{ + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + return priv->autoprune; +} + +/** + * flatpak_related_ref_get_subpaths: + * @self: a #FlatpakRelatedRef + * + * Returns the subpaths that should be installed/updated for the ref. + * This returns %NULL if all files should be installed. + * + * Returns: (transfer none): A strv, or %NULL + * + * Since: 0.6.7 + */ +const char * const * +flatpak_related_ref_get_subpaths (FlatpakRelatedRef *self) +{ + FlatpakRelatedRefPrivate *priv = flatpak_related_ref_get_instance_private (self); + + return (const char * const *) priv->subpaths; +} + + +FlatpakRelatedRef * +flatpak_related_ref_new (const char *collection_id, + const char *full_ref, + const char *commit, + char **subpaths, + gboolean download, + gboolean delete) +{ + FlatpakRefKind kind = FLATPAK_REF_KIND_APP; + FlatpakRelatedRef *ref; + + g_auto(GStrv) parts = NULL; + + parts = g_strsplit (full_ref, "/", -1); + + if (strcmp (parts[0], "app") != 0) + kind = FLATPAK_REF_KIND_RUNTIME; + + /* Canonicalize the "no subpaths" case */ + if (subpaths && *subpaths == NULL) + subpaths = NULL; + + ref = g_object_new (FLATPAK_TYPE_RELATED_REF, + "kind", kind, + "name", parts[1], + "arch", parts[2], + "branch", parts[3], + "commit", commit, + "subpaths", subpaths, + "should-download", download, + "should-delete", delete, +#ifdef FLATPAK_ENABLE_P2P + "collection-id", collection_id, +#endif /* FLATPAK_ENABLE_P2P */ + NULL); + + return ref; +} diff -Nru flatpak-0.11.7/common/flatpak-related-ref.h flatpak-0.11.8.3/common/flatpak-related-ref.h --- flatpak-0.11.7/common/flatpak-related-ref.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-related-ref.h 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_RELATED_REF_H__ +#define __FLATPAK_RELATED_REF_H__ + +typedef struct _FlatpakRelatedRef FlatpakRelatedRef; + +#include +#include + +#define FLATPAK_TYPE_RELATED_REF flatpak_related_ref_get_type () +#define FLATPAK_RELATED_REF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_RELATED_REF, FlatpakRelatedRef)) +#define FLATPAK_IS_RELATED_REF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_RELATED_REF)) + +FLATPAK_EXTERN GType flatpak_related_ref_get_type (void); + +struct _FlatpakRelatedRef +{ + FlatpakRef parent; +}; + +typedef struct +{ + FlatpakRefClass parent_class; +} FlatpakRelatedRefClass; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRelatedRef, g_object_unref) +#endif + +FLATPAK_EXTERN const char * const *flatpak_related_ref_get_subpaths (FlatpakRelatedRef *self); +FLATPAK_EXTERN gboolean flatpak_related_ref_should_download (FlatpakRelatedRef *self); +FLATPAK_EXTERN gboolean flatpak_related_ref_should_delete (FlatpakRelatedRef *self); +FLATPAK_EXTERN gboolean flatpak_related_ref_should_autoprune (FlatpakRelatedRef *self); + +#endif /* __FLATPAK_RELATED_REF_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-related-ref-private.h flatpak-0.11.8.3/common/flatpak-related-ref-private.h --- flatpak-0.11.7/common/flatpak-related-ref-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-related-ref-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_RELATED_REF_PRIVATE_H__ +#define __FLATPAK_RELATED_REF_PRIVATE_H__ + +#include +#include + +FlatpakRelatedRef *flatpak_related_ref_new (const char *collection_id, + const char *full_ref, + const char *commit, + char **subpaths, + gboolean download, + gboolean delete); + +#endif /* __FLATPAK_RELATED_REF_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-remote.c flatpak-0.11.8.3/common/flatpak-remote.c --- flatpak-0.11.7/common/flatpak-remote.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,890 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include "flatpak-utils-private.h" +#include "flatpak-remote-private.h" +#include "flatpak-remote-ref-private.h" +#include "flatpak-enum-types.h" + +#include +#include + +#ifdef FLATPAK_ENABLE_P2P +#include +#endif /* FLATPAK_ENABLE_P2P */ + +/** + * SECTION:flatpak-remote + * @Short_description: Remote repository + * @Title: FlatpakRemote + * + * A #FlatpakRemote object provides information about a remote + * repository (or short: remote) that has been configured. + * + * At its most basic level, a remote has a name and the URL for + * the repository. In addition, they provide some additional + * information that can be useful when presenting repositories + * in a UI, such as a title, a priority or a "don't enumerate" + * flags. + * + * To obtain FlatpakRemote objects for the configured remotes + * on a system, use flatpak_installation_list_remotes() or + * flatpak_installation_get_remote_by_name(). + */ + +typedef struct _FlatpakRemotePrivate FlatpakRemotePrivate; + +struct _FlatpakRemotePrivate +{ + char *name; + FlatpakDir *dir; + + char *local_url; + char *local_collection_id; + char *local_title; + char *local_default_branch; + gboolean local_gpg_verify; + gboolean local_noenumerate; + gboolean local_nodeps; + gboolean local_disabled; + int local_prio; + FlatpakRemoteType type; + + guint local_url_set : 1; + guint local_collection_id_set : 1; + guint local_title_set : 1; + guint local_default_branch_set : 1; + guint local_gpg_verify_set : 1; + guint local_noenumerate_set : 1; + guint local_nodeps_set : 1; + guint local_disabled_set : 1; + guint local_prio_set : 1; + + GBytes *local_gpg_key; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakRemote, flatpak_remote, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_NAME, + PROP_TYPE, +}; + +static void +flatpak_remote_finalize (GObject *object) +{ + FlatpakRemote *self = FLATPAK_REMOTE (object); + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + g_free (priv->name); + if (priv->dir) + g_object_unref (priv->dir); + if (priv->local_gpg_key) + g_bytes_unref (priv->local_gpg_key); + + g_free (priv->local_url); + g_free (priv->local_collection_id); + g_free (priv->local_title); + g_free (priv->local_default_branch); + + G_OBJECT_CLASS (flatpak_remote_parent_class)->finalize (object); +} + +static void +flatpak_remote_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakRemote *self = FLATPAK_REMOTE (object); + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + switch (prop_id) + { + case PROP_NAME: + g_clear_pointer (&priv->name, g_free); + priv->name = g_value_dup_string (value); + break; + + case PROP_TYPE: + priv->type = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_remote_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakRemote *self = FLATPAK_REMOTE (object); + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_TYPE: + g_value_set_enum (value, priv->type); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_remote_class_init (FlatpakRemoteClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_remote_get_property; + object_class->set_property = flatpak_remote_set_property; + object_class->finalize = flatpak_remote_finalize; + + /** + * FlatpakRemote:name: + * + * Name of the remote, as used in configuration files and when interfacing + * with OSTree. This is typically human readable, but could be generated, and + * must conform to ostree_validate_remote_name(). It should typically not be + * presented in the UI. + */ + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Name", + "The name of the remote", + NULL, + G_PARAM_READWRITE)); + + /** + * FlatpakRemote:type: + * + * The type of the remote: whether it comes from static configuration files + * (@FLATPAK_REMOTE_TYPE_STATIC) or has been dynamically found from the local + * network or a mounted USB drive (@FLATPAK_REMOTE_TYPE_LAN, + * @FLATPAK_REMOTE_TYPE_USB). Dynamic remotes may be added and removed over + * time. + * + * Since: 0.9.8 + */ + g_object_class_install_property (object_class, + PROP_TYPE, + g_param_spec_enum ("type", + "Type", + "The type of the remote", + FLATPAK_TYPE_REMOTE_TYPE, + FLATPAK_REMOTE_TYPE_STATIC, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +flatpak_remote_init (FlatpakRemote *self) +{ +} + +/** + * flatpak_remote_get_name: + * @self: a #FlatpakRemote + * + * Returns the name of the remote repository. + * + * Returns: (transfer none): the name + */ +const char * +flatpak_remote_get_name (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + return priv->name; +} + +/** + * flatpak_remote_get_appstream_dir: + * @self: a #FlatpakRemote + * @arch: (nullable): which architecture to fetch (default: current architecture) + * + * Returns the directory where this remote will store locally cached + * appstream information for the specified @arch. + * + * Returns: (transfer full): a #GFile + **/ +GFile * +flatpak_remote_get_appstream_dir (FlatpakRemote *self, + const char *arch) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + g_autofree char *subdir = NULL; + + if (priv->dir == NULL) + return NULL; + + if (arch == NULL) + arch = flatpak_get_arch (); + + subdir = g_strdup_printf ("appstream/%s/%s/active", priv->name, arch); + return g_file_resolve_relative_path (flatpak_dir_get_path (priv->dir), + subdir); +} + +/** + * flatpak_remote_get_appstream_timestamp: + * @self: a #FlatpakRemote + * @arch: (nullable): which architecture to fetch (default: current architecture) + * + * Returns the timestamp file that will be updated whenever the appstream information + * has been updated (or tried to update) for the specified @arch. + * + * Returns: (transfer full): a #GFile + **/ +GFile * +flatpak_remote_get_appstream_timestamp (FlatpakRemote *self, + const char *arch) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + g_autofree char *subdir = NULL; + + if (priv->dir == NULL) + return NULL; + + if (arch == NULL) + arch = flatpak_get_arch (); + + subdir = g_strdup_printf ("appstream/%s/%s/.timestamp", priv->name, arch); + return g_file_resolve_relative_path (flatpak_dir_get_path (priv->dir), + subdir); +} + +/** + * flatpak_remote_get_url: + * @self: a #FlatpakRemote + * + * Returns the repository URL of this remote. + * + * Returns: (transfer full): the URL + */ +char * +flatpak_remote_get_url (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + char *url; + + if (priv->local_url_set) + return g_strdup (priv->local_url); + + if (priv->dir) + { + OstreeRepo *repo = flatpak_dir_get_repo (priv->dir); + if (ostree_repo_remote_get_url (repo, priv->name, &url, NULL)) + return url; + } + + return NULL; +} + +/** + * flatpak_remote_set_url: + * @self: a #FlatpakRemote + * @url: The new url + * + * Sets the repository URL of this remote. + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_url (FlatpakRemote *self, + const char *url) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + g_free (priv->local_url); + priv->local_url = g_strdup (url); + priv->local_url_set = TRUE; +} + +/** + * flatpak_remote_get_collection_id: + * @self: a #FlatpakRemote + * + * Returns the repository collection ID of this remote, if set. + * + * Returns: (transfer full) (nullable): the collection ID, or %NULL if unset + */ +char * +flatpak_remote_get_collection_id (FlatpakRemote *self) +{ +#ifdef FLATPAK_ENABLE_P2P + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_collection_id_set) + return g_strdup (priv->local_collection_id); + + if (priv->dir) + return flatpak_dir_get_remote_collection_id (priv->dir, priv->name); +#endif /** FLATPAK_ENABLE_P2P */ + + return NULL; +} + +/** + * flatpak_remote_set_collection_id: + * @self: a #FlatpakRemote + * @collection_id: (nullable): The new collection ID, or %NULL to unset + * + * Sets the repository collection ID of this remote. + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_collection_id (FlatpakRemote *self, + const char *collection_id) +{ +#ifdef FLATPAK_ENABLE_P2P + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (collection_id != NULL && *collection_id == '\0') + collection_id = NULL; + + g_free (priv->local_collection_id); + priv->local_collection_id = g_strdup (collection_id); + priv->local_collection_id_set = TRUE; +#endif /* FLATPAK_ENABLE_P2P */ +} + +/** + * flatpak_remote_get_title: + * @self: a #FlatpakRemote + * + * Returns the title of the remote. + * + * Returns: (transfer full): the title + */ +char * +flatpak_remote_get_title (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_title_set) + return g_strdup (priv->local_title); + + if (priv->dir) + return flatpak_dir_get_remote_title (priv->dir, priv->name); + + return NULL; +} + +/** + * flatpak_remote_set_title: + * @self: a #FlatpakRemote + * @title: The new title + * + * Sets the repository title of this remote. + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_title (FlatpakRemote *self, + const char *title) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + g_free (priv->local_title); + priv->local_title = g_strdup (title); + priv->local_title_set = TRUE; +} + +/** + * flatpak_remote_get_default_branch: + * @self: a #FlatpakRemote + * + * Returns the default branch configured for the remote. + * + * Returns: (transfer full): the default branch, or %NULL + * + * Since: 0.6.12 + */ +char * +flatpak_remote_get_default_branch (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_default_branch_set) + return g_strdup (priv->local_default_branch); + + if (priv->dir) + return flatpak_dir_get_remote_default_branch (priv->dir, priv->name); + + return NULL; +} + +/** + * flatpak_remote_set_default_branch: + * @self: a #FlatpakRemote + * @default_branch: The new default_branch + * + * Sets the default branch configured for this remote. + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + * + * Since: 0.6.12 + */ +void +flatpak_remote_set_default_branch (FlatpakRemote *self, + const char *default_branch) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + g_free (priv->local_default_branch); + priv->local_default_branch = g_strdup (default_branch); + priv->local_default_branch_set = TRUE; +} + +/** + * flatpak_remote_get_noenumerate: + * @self: a #FlatpakRemote + * + * Returns whether this remote should be used to list applications. + * + * Returns: whether the remote is marked as "don't enumerate" + */ +gboolean +flatpak_remote_get_noenumerate (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_noenumerate_set) + return priv->local_noenumerate; + + if (priv->dir) + return flatpak_dir_get_remote_noenumerate (priv->dir, priv->name); + + return FALSE; +} + +/** + * flatpak_remote_set_noenumerate: + * @self: a #FlatpakRemote + * @noenumerate: a bool + * + * Sets the noenumeration config of this remote. See flatpak_remote_get_noenumerate(). + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_noenumerate (FlatpakRemote *self, + gboolean noenumerate) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + priv->local_noenumerate = noenumerate; + priv->local_noenumerate_set = TRUE; +} + +/** + * flatpak_remote_get_nodeps: + * @self: a #FlatpakRemote + * + * Returns whether this remote should be used to find dependencies. + * + * Returns: whether the remote is marked as "don't use for dependencies" + */ +gboolean +flatpak_remote_get_nodeps (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_nodeps_set) + return priv->local_nodeps; + + if (priv->dir) + return flatpak_dir_get_remote_nodeps (priv->dir, priv->name); + + return FALSE; +} + +/** + * flatpak_remote_set_nodeps: + * @self: a #FlatpakRemote + * @nodeps: a bool + * + * Sets the nodeps config of this remote. See flatpak_remote_get_nodeps(). + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_nodeps (FlatpakRemote *self, + gboolean nodeps) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + priv->local_nodeps = nodeps; + priv->local_nodeps_set = TRUE; +} + +/** + * flatpak_remote_get_disabled: + * @self: a #FlatpakRemote + * + * Returns whether this remote is disabled. + * + * Returns: whether the remote is marked as disabled + */ +gboolean +flatpak_remote_get_disabled (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_disabled_set) + return priv->local_disabled; + + if (priv->dir) + return flatpak_dir_get_remote_disabled (priv->dir, priv->name); + + return FALSE; +} +/** + * flatpak_remote_set_disabled: + * @self: a #FlatpakRemote + * @disabled: a bool + * + * Sets the disabled config of this remote. See flatpak_remote_get_disabled(). + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_disabled (FlatpakRemote *self, + gboolean disabled) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + priv->local_disabled = disabled; + priv->local_disabled_set = TRUE; +} + +/** + * flatpak_remote_get_prio: + * @self: a #FlatpakRemote + * + * Returns the priority for the remote. + * + * Returns: the priority + */ +int +flatpak_remote_get_prio (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_prio_set) + return priv->local_prio; + + if (priv->dir) + return flatpak_dir_get_remote_prio (priv->dir, priv->name); + + return 1; +} + +/** + * flatpak_remote_set_prio: + * @self: a #FlatpakRemote + * @prio: a bool + * + * Sets the prio config of this remote. See flatpak_remote_get_prio(). + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_prio (FlatpakRemote *self, + int prio) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + priv->local_prio = prio; + priv->local_prio_set = TRUE; +} + +/** + * flatpak_remote_get_gpg_verify: + * @self: a #FlatpakRemote + * + * Returns whether GPG verification is enabled for the remote. + * + * Returns: whether GPG verification is enabled + */ +gboolean +flatpak_remote_get_gpg_verify (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + gboolean res; + + if (priv->local_gpg_verify_set) + return priv->local_gpg_verify; + + if (priv->dir) + { + OstreeRepo *repo = flatpak_dir_get_repo (priv->dir); + if (ostree_repo_remote_get_gpg_verify (repo, priv->name, &res, NULL)) + return res; + } + + return FALSE; +} + +/** + * flatpak_remote_set_gpg_verify: + * @self: a #FlatpakRemote + * @gpg_verify: a bool + * + * Sets the gpg_verify config of this remote. See flatpak_remote_get_gpg_verify(). + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_gpg_verify (FlatpakRemote *self, + gboolean gpg_verify) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + priv->local_gpg_verify = gpg_verify; + priv->local_gpg_verify_set = TRUE; +} + +/** + * flatpak_remote_set_gpg_key: + * @self: a #FlatpakRemote + * @gpg_key: a #GBytes with gpg binary key data + * + * Sets the trusted gpg key for this remote. + * + * Note: This is a local modification of this object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + */ +void +flatpak_remote_set_gpg_key (FlatpakRemote *self, + GBytes *gpg_key) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + if (priv->local_gpg_key != NULL) + g_bytes_unref (priv->local_gpg_key); + priv->local_gpg_key = g_bytes_ref (gpg_key); +} + +FlatpakRemote * +flatpak_remote_new_with_dir (const char *name, + FlatpakDir *dir) +{ + FlatpakRemotePrivate *priv; + FlatpakRemote *self = g_object_new (FLATPAK_TYPE_REMOTE, + "name", name, + NULL); + + priv = flatpak_remote_get_instance_private (self); + if (dir) + priv->dir = g_object_ref (dir); + + return self; +} + +#ifdef FLATPAK_ENABLE_P2P +static FlatpakRemoteType +repo_finder_to_remote_type (OstreeRepoFinder *repo_finder) +{ + if (OSTREE_IS_REPO_FINDER_AVAHI (repo_finder)) + return FLATPAK_REMOTE_TYPE_LAN; + else if (OSTREE_IS_REPO_FINDER_MOUNT (repo_finder)) + return FLATPAK_REMOTE_TYPE_USB; + else + return FLATPAK_REMOTE_TYPE_STATIC; +} + +FlatpakRemote * +flatpak_remote_new_from_ostree (OstreeRemote *remote, + OstreeRepoFinder *repo_finder, + FlatpakDir *dir) +{ + g_autofree gchar *url = NULL; + FlatpakRemotePrivate *priv; + FlatpakRemote *self = g_object_new (FLATPAK_TYPE_REMOTE, + "name", ostree_remote_get_name (remote), + "type", repo_finder_to_remote_type (repo_finder), + NULL); + + priv = flatpak_remote_get_instance_private (self); + if (dir) + priv->dir = g_object_ref (dir); + + url = ostree_remote_get_url (remote); + if (url != NULL) + flatpak_remote_set_url (self, url); + + return self; +} +#endif /* FLATPAK_ENABLE_P2P */ + +/** + * flatpak_remote_new: + * @name: a name + * + * Returns a new remote object which can be used to configure a new remote. + * + * Note: This is a local configuration object, you must commit changes + * using flatpak_installation_modify_remote() for the changes to take + * effect. + * + * Returns: (transfer full): a new #FlatpakRemote + **/ +FlatpakRemote * +flatpak_remote_new (const char *name) +{ + return flatpak_remote_new_with_dir (name, NULL); +} + +gboolean +flatpak_remote_commit (FlatpakRemote *self, + FlatpakDir *dir, + GCancellable *cancellable, + GError **error) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + OstreeRepo *repo; + g_autofree char *url = NULL; + g_autoptr(GKeyFile) config = NULL; + g_autofree char *group = g_strdup_printf ("remote \"%s\"", priv->name); + + url = flatpak_remote_get_url (self); + if (url == NULL || *url == 0) + return flatpak_fail (error, "No url specified"); + + if (priv->type != FLATPAK_REMOTE_TYPE_STATIC) + return flatpak_fail (error, "Dynamic remote cannot be committed"); + + repo = flatpak_dir_get_repo (dir); + if (repo == NULL) + config = g_key_file_new (); + else + config = ostree_repo_copy_config (repo); + + if (priv->local_url_set) + g_key_file_set_string (config, group, "url", priv->local_url); + + if (priv->local_collection_id_set) + { + if (priv->local_collection_id != NULL) + { + g_key_file_set_string (config, group, "collection-id", priv->local_collection_id); + + /* When a collection ID is set, flatpak uses signed per-repo and + * per-commit metadata instead of summary signatures. */ + g_key_file_set_boolean (config, group, "gpg-verify-summary", FALSE); + } + else + { + g_autoptr(GError) local_error = NULL; + gboolean gpg_verify_value; + + g_key_file_remove_key (config, group, "collection-id", NULL); + + /* Without a collection ID gpg-verify-summary should go back to + * matching gpg-verify. */ + gpg_verify_value = g_key_file_get_boolean (config, group, "gpg-verify", &local_error); + if (local_error == NULL) + g_key_file_set_boolean (config, group, "gpg-verify-summary", gpg_verify_value); + } + } + + if (priv->local_title_set) + g_key_file_set_string (config, group, "xa.title", priv->local_title); + + if (priv->local_default_branch_set) + g_key_file_set_string (config, group, "xa.default-branch", priv->local_default_branch); + + if (priv->local_gpg_verify_set) + { + g_key_file_set_boolean (config, group, "gpg-verify", priv->local_gpg_verify); + + if (!priv->local_collection_id_set || priv->local_collection_id == NULL) + g_key_file_set_boolean (config, group, "gpg-verify-summary", priv->local_gpg_verify); + } + + if (priv->local_noenumerate_set) + g_key_file_set_boolean (config, group, "xa.noenumerate", priv->local_noenumerate); + + if (priv->local_disabled_set) + g_key_file_set_boolean (config, group, "xa.disable", priv->local_disabled); + + if (priv->local_prio_set) + { + g_autofree char *prio_as_string = g_strdup_printf ("%d", priv->local_prio); + g_key_file_set_string (config, group, "xa.prio", prio_as_string); + } + + return flatpak_dir_modify_remote (dir, priv->name, config, priv->local_gpg_key, cancellable, error); +} + +/** + * flatpak_remote_get_remote_type: + * @self: a #FlatpakRemote + * + * Get the value of #FlatpakRemote:type. + * + * Returns: the type of remote this is + * Since: 0.9.8 + */ +FlatpakRemoteType +flatpak_remote_get_remote_type (FlatpakRemote *self) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + + g_return_val_if_fail (FLATPAK_IS_REMOTE (self), FLATPAK_REMOTE_TYPE_STATIC); + + return priv->type; +} diff -Nru flatpak-0.11.7/common/flatpak-remote.h flatpak-0.11.8.3/common/flatpak-remote.h --- flatpak-0.11.7/common/flatpak-remote.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,108 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_REMOTE_H__ +#define __FLATPAK_REMOTE_H__ + +/** + * FlatpakRemoteType: + * @FLATPAK_REMOTE_TYPE_STATIC: Statically configured remote + * @FLATPAK_REMOTE_TYPE_USB: Dynamically detected local pathname remote + * @FLATPAK_REMOTE_TYPE_LAN: Dynamically detected network remote + * + * Different types of @FlatpakRemote. + */ +typedef enum +{ + FLATPAK_REMOTE_TYPE_STATIC, + FLATPAK_REMOTE_TYPE_USB, + FLATPAK_REMOTE_TYPE_LAN, +} FlatpakRemoteType; + +typedef struct _FlatpakRemote FlatpakRemote; + +#include +#include + +#define FLATPAK_TYPE_REMOTE flatpak_remote_get_type () +#define FLATPAK_REMOTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_REMOTE, FlatpakRemote)) +#define FLATPAK_IS_REMOTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_REMOTE)) + +FLATPAK_EXTERN GType flatpak_remote_get_type (void); + +struct _FlatpakRemote +{ + GObject parent; +}; + +typedef struct +{ + GObjectClass parent_class; +} FlatpakRemoteClass; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemote, g_object_unref) +#endif + +FLATPAK_EXTERN FlatpakRemote * flatpak_remote_new (const char *name); + +FLATPAK_EXTERN const char * flatpak_remote_get_name (FlatpakRemote *self); +FLATPAK_EXTERN GFile * flatpak_remote_get_appstream_dir (FlatpakRemote *self, + const char *arch); +FLATPAK_EXTERN GFile * flatpak_remote_get_appstream_timestamp (FlatpakRemote *self, + const char *arch); +FLATPAK_EXTERN char * flatpak_remote_get_url (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_url (FlatpakRemote *self, + const char *url); +FLATPAK_EXTERN char * flatpak_remote_get_collection_id (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_collection_id (FlatpakRemote *self, + const char *collection_id); +FLATPAK_EXTERN char * flatpak_remote_get_title (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_title (FlatpakRemote *self, + const char *title); +FLATPAK_EXTERN char * flatpak_remote_get_default_branch (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_default_branch (FlatpakRemote *self, + const char *default_branch); +FLATPAK_EXTERN gboolean flatpak_remote_get_gpg_verify (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_gpg_verify (FlatpakRemote *self, + gboolean gpg_verify); +FLATPAK_EXTERN void flatpak_remote_set_gpg_key (FlatpakRemote *self, + GBytes *gpg_key); +FLATPAK_EXTERN gboolean flatpak_remote_get_noenumerate (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_noenumerate (FlatpakRemote *self, + gboolean noenumerate); +FLATPAK_EXTERN gboolean flatpak_remote_get_nodeps (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_nodeps (FlatpakRemote *self, + gboolean nodeps); +FLATPAK_EXTERN gboolean flatpak_remote_get_disabled (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_disabled (FlatpakRemote *self, + gboolean disabled); +FLATPAK_EXTERN int flatpak_remote_get_prio (FlatpakRemote *self); +FLATPAK_EXTERN void flatpak_remote_set_prio (FlatpakRemote *self, + int prio); + +FLATPAK_EXTERN FlatpakRemoteType flatpak_remote_get_remote_type (FlatpakRemote *self); + + +#endif /* __FLATPAK_REMOTE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-remote-private.h flatpak-0.11.8.3/common/flatpak-remote-private.h --- flatpak-0.11.7/common/flatpak-remote-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_REMOTE_PRIVATE_H__ +#define __FLATPAK_REMOTE_PRIVATE_H__ + +#include +#include +#include + +FlatpakRemote *flatpak_remote_new_with_dir (const char *name, + FlatpakDir *dir); + +#ifdef FLATPAK_ENABLE_P2P +FlatpakRemote *flatpak_remote_new_from_ostree (OstreeRemote *remote, + OstreeRepoFinder *repo_finder, + FlatpakDir *dir); +#endif /* FLATPAK_ENABLE_P2P */ + +gboolean flatpak_remote_commit (FlatpakRemote *self, + FlatpakDir *dir, + GCancellable *cancellable, + GError **error); + +#endif /* __FLATPAK_REMOTE_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-remote-ref.c flatpak-0.11.8.3/common/flatpak-remote-ref.c --- flatpak-0.11.7/common/flatpak-remote-ref.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote-ref.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,381 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include + +#include "flatpak-utils-private.h" +#include "flatpak-remote-ref-private.h" +#include "flatpak-remote-ref.h" +#include "flatpak-enum-types.h" + +/** + * SECTION:flatpak-remote-ref + * @Title: FlatpakRemoteRef + * @Short_description: Remote application reference + * + * A FlatpakRemoteRef provides information about an application or runtime + * (in short: ref) that is available from a remote repository. + */ +typedef struct _FlatpakRemoteRefPrivate FlatpakRemoteRefPrivate; + +struct _FlatpakRemoteRefPrivate +{ + char *remote_name; + guint64 installed_size; + guint64 download_size; + GBytes *metadata; + char *eol; + char *eol_rebase; + +}; + +G_DEFINE_TYPE_WITH_PRIVATE (FlatpakRemoteRef, flatpak_remote_ref, FLATPAK_TYPE_REF) + +enum { + PROP_0, + + PROP_REMOTE_NAME, + PROP_INSTALLED_SIZE, + PROP_DOWNLOAD_SIZE, + PROP_METADATA, + PROP_EOL, + PROP_EOL_REBASE, +}; + +static void +flatpak_remote_ref_finalize (GObject *object) +{ + FlatpakRemoteRef *self = FLATPAK_REMOTE_REF (object); + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + g_free (priv->remote_name); + g_free (priv->eol); + g_free (priv->eol_rebase); + g_clear_pointer (&priv->metadata, g_bytes_unref); + + G_OBJECT_CLASS (flatpak_remote_ref_parent_class)->finalize (object); +} + +static void +flatpak_remote_ref_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakRemoteRef *self = FLATPAK_REMOTE_REF (object); + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_REMOTE_NAME: + g_clear_pointer (&priv->remote_name, g_free); + priv->remote_name = g_value_dup_string (value); + break; + + case PROP_INSTALLED_SIZE: + priv->installed_size = g_value_get_uint64 (value); + break; + + case PROP_DOWNLOAD_SIZE: + priv->download_size = g_value_get_uint64 (value); + break; + + case PROP_METADATA: + g_clear_pointer (&priv->metadata, g_bytes_unref); + priv->metadata = g_value_get_boxed (value) ? g_bytes_ref (g_value_get_boxed (value)) : NULL; + break; + + case PROP_EOL: + g_clear_pointer (&priv->eol, g_free); + priv->eol = g_value_dup_string (value); + break; + + case PROP_EOL_REBASE: + g_clear_pointer (&priv->eol_rebase, g_free); + priv->eol_rebase = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_remote_ref_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakRemoteRef *self = FLATPAK_REMOTE_REF (object); + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + switch (prop_id) + { + case PROP_REMOTE_NAME: + g_value_set_string (value, priv->remote_name); + break; + + case PROP_INSTALLED_SIZE: + g_value_set_uint64 (value, priv->installed_size); + break; + + case PROP_DOWNLOAD_SIZE: + g_value_set_uint64 (value, priv->installed_size); + break; + + case PROP_METADATA: + g_value_set_boxed (value, priv->metadata); + break; + + case PROP_EOL: + g_value_set_string (value, priv->eol); + break; + + case PROP_EOL_REBASE: + g_value_set_string (value, priv->eol_rebase); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_remote_ref_class_init (FlatpakRemoteRefClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = flatpak_remote_ref_get_property; + object_class->set_property = flatpak_remote_ref_set_property; + object_class->finalize = flatpak_remote_ref_finalize; + + g_object_class_install_property (object_class, + PROP_REMOTE_NAME, + g_param_spec_string ("remote-name", + "Remote Name", + "The name of the remote", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_INSTALLED_SIZE, + g_param_spec_uint64 ("installed-size", + "Installed Size", + "The installed size of the application", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_DOWNLOAD_SIZE, + g_param_spec_uint64 ("download-size", + "Download Size", + "The download size of the application", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_METADATA, + g_param_spec_boxed ("metadata", + "Metadata", + "The metadata info for the application", + G_TYPE_BYTES, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_EOL, + g_param_spec_string ("end-of-life", + "End of life", + "The reason for the ref to be end of life", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_EOL_REBASE, + g_param_spec_string ("end-of-life-rebase", + "End of life rebase", + "The new ref for the end of lifeed ref", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); +} + +static void +flatpak_remote_ref_init (FlatpakRemoteRef *self) +{ +} + +/** + * flatpak_remote_ref_get_remote_name: + * @self: a #FlatpakRemoteRef + * + * Gets the remote name of the ref. + * + * Returns: (transfer none): the remote name + */ +const char * +flatpak_remote_ref_get_remote_name (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->remote_name; +} + +/** + * flatpak_remote_ref_get_installed_size: + * @self: a #FlatpakRemoteRef + * + * Returns the installed size of the ref. + * + * Returns: the installed size + */ +guint64 +flatpak_remote_ref_get_installed_size (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->installed_size; +} + +/** + * flatpak_remote_ref_get_download_size: + * @self: a #FlatpakRemoteRef + * + * Returns the download size of the ref. + * + * Returns: the download size + */ +guint64 +flatpak_remote_ref_get_download_size (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->download_size; +} + +/** + * flatpak_remote_ref_get_metadata: + * @self: a #FlatpakRemoteRef + * + * Returns the app metadata from the metadata cach of the ref. + * + * Returns: (transfer none) (nullable): a #GBytes with the metadata file + * contents or %NULL + */ +GBytes * +flatpak_remote_ref_get_metadata (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->metadata; +} + +/** + * flatpak_remote_ref_get_eol: + * @self: a #FlatpakRemoteRef + * + * Returns the end-of-life reason string, or %NULL if the + * ref is not end-of-lifed. + * + * Returns: (transfer none): the end-of-life reason or %NULL + */ +const char * +flatpak_remote_ref_get_eol (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->eol; +} + +/** + * flatpak_remote_ref_get_eol_rebase: + * @self: a #FlatpakRemoteRef + * + * Returns the end-of-life rebased ref, or %NULL if the + * ref is not end-of-lifed. + * + * Returns: (transfer none): the end-of-life rebased ref or %NULL + */ +const char * +flatpak_remote_ref_get_eol_rebase (FlatpakRemoteRef *self) +{ + FlatpakRemoteRefPrivate *priv = flatpak_remote_ref_get_instance_private (self); + + return priv->eol_rebase; +} + +FlatpakRemoteRef * +flatpak_remote_ref_new (FlatpakCollectionRef *coll_ref, + const char *commit, + const char *remote_name, + FlatpakRemoteState *state) +{ + FlatpakRefKind kind = FLATPAK_REF_KIND_APP; + guint64 download_size = 0, installed_size = 0; + const char *metadata = NULL; + g_autoptr(GBytes) metadata_bytes = NULL; + g_auto(GStrv) parts = NULL; + FlatpakRemoteRef *ref; + g_autoptr(GVariant) sparse = NULL; + const char *full_ref = coll_ref->ref_name; + const char *eol = NULL; + const char *eol_rebase = NULL; + + parts = flatpak_decompose_ref (full_ref, NULL); + if (parts == NULL) + return NULL; + + if (state && + !flatpak_remote_state_lookup_cache (state, full_ref, + &download_size, &installed_size, &metadata, + NULL)) + { + g_debug ("Can't find metadata for ref %s", full_ref); + } + + if (metadata) + metadata_bytes = g_bytes_new (metadata, strlen (metadata)); + + if (state) + sparse = flatpak_remote_state_lookup_sparse_cache (state, full_ref, NULL); + + if (sparse) + { + g_variant_lookup (sparse, "eol", "&s", &eol); + g_variant_lookup (sparse, "eolr", "&s", &eol_rebase); + } + + if (strcmp (parts[0], "app") != 0) + kind = FLATPAK_REF_KIND_RUNTIME; + + ref = g_object_new (FLATPAK_TYPE_REMOTE_REF, + "kind", kind, + "name", parts[1], + "arch", parts[2], + "branch", parts[3], + "collection-id", coll_ref->collection_id, + "commit", commit, + "remote-name", remote_name, + "installed-size", installed_size, + "download-size", download_size, + "metadata", metadata_bytes, + "end-of-life", eol, + "end-of-life-rebase", eol_rebase, + NULL); + + return ref; +} diff -Nru flatpak-0.11.7/common/flatpak-remote-ref.h flatpak-0.11.8.3/common/flatpak-remote-ref.h --- flatpak-0.11.7/common/flatpak-remote-ref.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote-ref.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_REMOTE_REF_H__ +#define __FLATPAK_REMOTE_REF_H__ + +typedef struct _FlatpakRemoteRef FlatpakRemoteRef; + +#include +#include + +#define FLATPAK_TYPE_REMOTE_REF flatpak_remote_ref_get_type () +#define FLATPAK_REMOTE_REF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_REMOTE_REF, FlatpakRemoteRef)) +#define FLATPAK_IS_REMOTE_REF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_REMOTE_REF)) + +FLATPAK_EXTERN GType flatpak_remote_ref_get_type (void); + +struct _FlatpakRemoteRef +{ + FlatpakRef parent; +}; + +typedef struct +{ + FlatpakRefClass parent_class; +} FlatpakRemoteRefClass; + +FLATPAK_EXTERN const char * flatpak_remote_ref_get_remote_name (FlatpakRemoteRef *self); +FLATPAK_EXTERN guint64 flatpak_remote_ref_get_installed_size (FlatpakRemoteRef *self); +FLATPAK_EXTERN guint64 flatpak_remote_ref_get_download_size (FlatpakRemoteRef *self); +FLATPAK_EXTERN GBytes * flatpak_remote_ref_get_metadata (FlatpakRemoteRef *self); +FLATPAK_EXTERN const char * flatpak_remote_ref_get_eol (FlatpakRemoteRef *self); +FLATPAK_EXTERN const char * flatpak_remote_ref_get_eol_rebase (FlatpakRemoteRef *self); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemoteRef, g_object_unref) +#endif + +#endif /* __FLATPAK_REMOTE_REF_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-remote-ref-private.h flatpak-0.11.8.3/common/flatpak-remote-ref-private.h --- flatpak-0.11.7/common/flatpak-remote-ref-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-remote-ref-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright © 2015 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_REMOTE_REF_PRIVATE_H__ +#define __FLATPAK_REMOTE_REF_PRIVATE_H__ + +#include +#include + +FlatpakRemoteRef *flatpak_remote_ref_new (FlatpakCollectionRef *coll_ref, + const char *commit, + const char *remote_name, + FlatpakRemoteState *remote_state); + +#endif /* __FLATPAK_REMOTE_REF_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-run.c flatpak-0.11.8.3/common/flatpak-run.c --- flatpak-0.11.7/common/flatpak-run.c 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-run.c 2018-06-11 15:40:17.000000000 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,28 +46,16 @@ #include #include "libglnx/libglnx.h" -#include "flatpak-run.h" +#include "flatpak-run-private.h" #include "flatpak-proxy.h" -#include "flatpak-utils.h" -#include "flatpak-dir.h" -#include "flatpak-systemd-dbus.h" -#include "flatpak-document-dbus.h" -#include "lib/flatpak-error.h" +#include "flatpak-utils-private.h" +#include "flatpak-dir-private.h" +#include "flatpak-systemd-dbus-generated.h" +#include "flatpak-document-dbus-generated.h" +#include "flatpak-error.h" #define DEFAULT_SHELL "/bin/sh" -static gboolean -add_dbus_proxy_args (GPtrArray *argv_array, - GPtrArray *session_dbus_proxy_argv, - gboolean enable_session_logging, - GPtrArray *system_dbus_proxy_argv, - gboolean enable_system_logging, - GPtrArray *a11y_dbus_proxy_argv, - gboolean enable_a11y_logging, - int sync_fds[2], - const char *app_info_path, - GError **error); - static char * extract_unix_path_from_dbus_address (const char *address) { @@ -163,34 +152,6 @@ #endif /* ENABLE_XAUTH */ static void -add_args (GPtrArray *argv_array, ...) -{ - va_list args; - const gchar *arg; - - va_start (args, argv_array); - while ((arg = va_arg (args, const gchar *))) - g_ptr_array_add (argv_array, g_strdup (arg)); - va_end (args); -} - -static void -add_args_data_fd (GPtrArray *argv_array, - GArray *fd_array, - const char *op, - int fd, - const char *path_optional) -{ - g_autofree char *fd_str = g_strdup_printf ("%d", fd); - if (fd_array) - g_array_append_val (fd_array, fd); - - add_args (argv_array, - op, fd_str, path_optional, - NULL); -} - -static void flatpak_run_add_x11_args (FlatpakBwrap *bwrap, gboolean allowed) { @@ -480,15 +441,22 @@ } static gboolean -flatpak_run_add_system_dbus_args (FlatpakContext *context, - FlatpakBwrap *bwrap, - GPtrArray *dbus_proxy_argv, - gboolean unrestricted) +flatpak_run_add_system_dbus_args (FlatpakBwrap *app_bwrap, + FlatpakBwrap *proxy_arg_bwrap, + FlatpakContext *context, + FlatpakRunFlags flags) { + gboolean unrestricted, no_proxy; const char *dbus_address = g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"); g_autofree char *real_dbus_address = NULL; g_autofree char *dbus_system_socket = NULL; + unrestricted = (context->sockets & FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS) != 0; + if (unrestricted) + g_debug ("Allowing system-dbus access"); + + no_proxy = (flags & FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY) != 0; + if (dbus_address != NULL) dbus_system_socket = extract_unix_path_from_dbus_address (dbus_address); else if (g_file_test ("/var/run/dbus/system_bus_socket", G_FILE_TEST_EXISTS)) @@ -496,15 +464,14 @@ if (dbus_system_socket != NULL && unrestricted) { - flatpak_bwrap_add_args (bwrap, + flatpak_bwrap_add_args (app_bwrap, "--bind", dbus_system_socket, "/run/dbus/system_bus_socket", NULL); - flatpak_bwrap_set_env (bwrap, "DBUS_SYSTEM_BUS_ADDRESS", "unix:path=/run/dbus/system_bus_socket", TRUE); + flatpak_bwrap_set_env (app_bwrap, "DBUS_SYSTEM_BUS_ADDRESS", "unix:path=/run/dbus/system_bus_socket", TRUE); return TRUE; } - else if (dbus_proxy_argv && - flatpak_context_get_needs_system_bus_proxy (context)) + else if (!no_proxy && flatpak_context_get_needs_system_bus_proxy (context)) { g_autofree char *proxy_socket = create_proxy_socket ("system-bus-proxy-XXXXXX"); @@ -516,14 +483,18 @@ else real_dbus_address = g_strdup_printf ("unix:path=%s", dbus_system_socket); - g_ptr_array_add (dbus_proxy_argv, g_strdup (real_dbus_address)); - g_ptr_array_add (dbus_proxy_argv, g_strdup (proxy_socket)); + flatpak_bwrap_add_args (proxy_arg_bwrap, real_dbus_address, proxy_socket, NULL); + if (!unrestricted) + flatpak_context_add_bus_filters (context, NULL, FALSE, proxy_arg_bwrap); - flatpak_bwrap_add_args (bwrap, + if ((flags & FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS) != 0) + flatpak_bwrap_add_args (proxy_arg_bwrap, "--log", NULL); + + flatpak_bwrap_add_args (app_bwrap, "--bind", proxy_socket, "/run/dbus/system_bus_socket", NULL); - flatpak_bwrap_set_env (bwrap, "DBUS_SYSTEM_BUS_ADDRESS", "unix:path=/run/dbus/system_bus_socket", TRUE); + flatpak_bwrap_set_env (app_bwrap, "DBUS_SYSTEM_BUS_ADDRESS", "unix:path=/run/dbus/system_bus_socket", TRUE); return TRUE; } @@ -531,42 +502,63 @@ } static gboolean -flatpak_run_add_session_dbus_args (FlatpakBwrap *bwrap, - GPtrArray *dbus_proxy_argv, - gboolean unrestricted) +flatpak_run_add_session_dbus_args (FlatpakBwrap *app_bwrap, + FlatpakBwrap *proxy_arg_bwrap, + FlatpakContext *context, + FlatpakRunFlags flags, + const char *app_id) { + gboolean unrestricted, no_proxy; const char *dbus_address = g_getenv ("DBUS_SESSION_BUS_ADDRESS"); char *dbus_session_socket = NULL; g_autofree char *sandbox_socket_path = g_strdup_printf ("/run/user/%d/bus", getuid ()); g_autofree char *sandbox_dbus_address = g_strdup_printf ("unix:path=/run/user/%d/bus", getuid ()); + unrestricted = (context->sockets & FLATPAK_CONTEXT_SOCKET_SESSION_BUS) != 0; + if (dbus_address == NULL) return FALSE; + if (unrestricted) + g_debug ("Allowing session-dbus access"); + + no_proxy = (flags & FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY) != 0; + dbus_session_socket = extract_unix_path_from_dbus_address (dbus_address); if (dbus_session_socket != NULL && unrestricted) { - flatpak_bwrap_add_args (bwrap, + flatpak_bwrap_add_args (app_bwrap, "--bind", dbus_session_socket, sandbox_socket_path, NULL); - flatpak_bwrap_set_env (bwrap, "DBUS_SESSION_BUS_ADDRESS", sandbox_dbus_address, TRUE); + flatpak_bwrap_set_env (app_bwrap, "DBUS_SESSION_BUS_ADDRESS", sandbox_dbus_address, TRUE); return TRUE; } - else if (dbus_proxy_argv && dbus_address != NULL) + else if (!no_proxy && dbus_address != NULL) { g_autofree char *proxy_socket = create_proxy_socket ("session-bus-proxy-XXXXXX"); if (proxy_socket == NULL) return FALSE; - g_ptr_array_add (dbus_proxy_argv, g_strdup (dbus_address)); - g_ptr_array_add (dbus_proxy_argv, g_strdup (proxy_socket)); + flatpak_bwrap_add_args (proxy_arg_bwrap, dbus_address, proxy_socket, NULL); - flatpak_bwrap_add_args (bwrap, + if (!unrestricted) + { + flatpak_context_add_bus_filters (context, app_id, TRUE, proxy_arg_bwrap); + + /* Allow calling any interface+method on all portals, but don't receive broadcasts */ + flatpak_bwrap_add_arg (proxy_arg_bwrap, + "--call=org.freedesktop.portal.*=*"); + } + + if ((flags & FLATPAK_RUN_FLAG_LOG_SESSION_BUS) != 0) + flatpak_bwrap_add_args (proxy_arg_bwrap, "--log", NULL); + + flatpak_bwrap_add_args (app_bwrap, "--bind", proxy_socket, sandbox_socket_path, NULL); - flatpak_bwrap_set_env (bwrap, "DBUS_SESSION_BUS_ADDRESS", sandbox_dbus_address, TRUE); + flatpak_bwrap_set_env (app_bwrap, "DBUS_SESSION_BUS_ADDRESS", sandbox_dbus_address, TRUE); return TRUE; } @@ -574,6 +566,237 @@ return FALSE; } +static gboolean +flatpak_run_add_a11y_dbus_args (FlatpakBwrap *app_bwrap, + FlatpakBwrap *proxy_arg_bwrap, + FlatpakContext *context, + FlatpakRunFlags flags) +{ + g_autoptr(GDBusConnection) session_bus = NULL; + g_autofree char *a11y_address = NULL; + g_autoptr(GError) local_error = NULL; + g_autoptr(GDBusMessage) reply = NULL; + g_autoptr(GDBusMessage) msg = NULL; + g_autofree char *proxy_socket = NULL; + + if ((flags & FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY) != 0) + return FALSE; + + session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + if (session_bus == NULL) + return FALSE; + + msg = g_dbus_message_new_method_call ("org.a11y.Bus", "/org/a11y/bus", "org.a11y.Bus", "GetAddress"); + g_dbus_message_set_body (msg, g_variant_new ("()")); + reply = + g_dbus_connection_send_message_with_reply_sync (session_bus, msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + 30000, + NULL, + NULL, + NULL); + if (reply) + { + if (g_dbus_message_to_gerror (reply, &local_error)) + { + if (!g_error_matches (local_error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + g_message ("Can't find a11y bus: %s", local_error->message); + } + else + { + g_variant_get (g_dbus_message_get_body (reply), + "(s)", &a11y_address); + } + } + + if (!a11y_address) + return FALSE; + + proxy_socket = create_proxy_socket ("a11y-bus-proxy-XXXXXX"); + if (proxy_socket == NULL) + return FALSE; + + g_autofree char *sandbox_socket_path = g_strdup_printf ("/run/user/%d/at-spi-bus", getuid ()); + g_autofree char *sandbox_dbus_address = g_strdup_printf ("unix:path=/run/user/%d/at-spi-bus", getuid ()); + + flatpak_bwrap_add_args (proxy_arg_bwrap, + a11y_address, + proxy_socket, "--filter", "--sloppy-names", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.Socket.Embed@/org/a11y/atspi/accessible/root", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.Socket.Unembed@/org/a11y/atspi/accessible/root", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.Registry.GetRegisteredEvents@/org/a11y/atspi/registry", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.GetKeystrokeListeners@/org/a11y/atspi/registry/deviceeventcontroller", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.GetDeviceEventListeners@/org/a11y/atspi/registry/deviceeventcontroller", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.NotifyListenersSync@/org/a11y/atspi/registry/deviceeventcontroller", + "--call=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.NotifyListenersAsync@/org/a11y/atspi/registry/deviceeventcontroller", + NULL); + + if ((flags & FLATPAK_RUN_FLAG_LOG_A11Y_BUS) != 0) + flatpak_bwrap_add_args (proxy_arg_bwrap, "--log", NULL); + + flatpak_bwrap_add_args (app_bwrap, + "--bind", proxy_socket, sandbox_socket_path, + NULL); + flatpak_bwrap_set_env (app_bwrap, "AT_SPI_BUS_ADDRESS", sandbox_dbus_address, TRUE); + + return TRUE; +} + +/* This wraps the argv in a bwrap call, primary to allow the + command to be run with a proper /.flatpak-info with data + taken from app_info_path */ +static gboolean +add_bwrap_wrapper (FlatpakBwrap *bwrap, + const char *app_info_path, + GError **error) +{ + glnx_autofd int app_info_fd = -1; + g_auto(GLnxDirFdIterator) dir_iter = { 0 }; + struct dirent *dent; + g_autofree char *proxy_socket_dir = g_build_filename (g_get_user_runtime_dir (), ".dbus-proxy/", NULL); + + app_info_fd = open (app_info_path, O_RDONLY | O_CLOEXEC); + if (app_info_fd == -1) + return glnx_throw_errno_prefix (error, _("Failed to open app info file")); + + if (!glnx_dirfd_iterator_init_at (AT_FDCWD, "/", FALSE, &dir_iter, error)) + return FALSE; + + flatpak_bwrap_add_arg (bwrap, flatpak_get_bwrap ()); + + while (TRUE) + { + glnx_autofd int o_path_fd = -1; + struct statfs stfs; + + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dir_iter, &dent, NULL, error)) + return FALSE; + + if (dent == NULL) + break; + + if (strcmp (dent->d_name, ".flatpak-info") == 0) + continue; + + /* O_PATH + fstatfs is the magic that we need to statfs without automounting the target */ + o_path_fd = openat (dir_iter.fd, dent->d_name, O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (o_path_fd == -1 || fstatfs (o_path_fd, &stfs) != 0 || stfs.f_type == AUTOFS_SUPER_MAGIC) + continue; /* AUTOFS mounts are risky and can cause us to block (see issue #1633), so ignore it. Its unlikely the proxy needs such a directory. */ + + if (dent->d_type == DT_DIR) + { + if (strcmp (dent->d_name, "tmp") == 0 || + strcmp (dent->d_name, "var") == 0 || + strcmp (dent->d_name, "run") == 0) + flatpak_bwrap_add_arg (bwrap, "--bind"); + else + flatpak_bwrap_add_arg (bwrap, "--ro-bind"); + + flatpak_bwrap_add_arg_printf (bwrap, "/%s", dent->d_name); + flatpak_bwrap_add_arg_printf (bwrap, "/%s", dent->d_name); + } + else if (dent->d_type == DT_LNK) + { + ssize_t symlink_size; + char path_buffer[PATH_MAX + 1]; + + symlink_size = readlinkat (dir_iter.fd, dent->d_name, path_buffer, sizeof (path_buffer) - 1); + if (symlink_size < 0) + { + glnx_set_error_from_errno (error); + return FALSE; + } + path_buffer[symlink_size] = 0; + + flatpak_bwrap_add_args (bwrap, "--symlink", path_buffer, NULL); + flatpak_bwrap_add_arg_printf (bwrap, "/%s", dent->d_name); + } + } + + flatpak_bwrap_add_args (bwrap, "--bind", proxy_socket_dir, proxy_socket_dir, NULL); + + /* This is a file rather than a bind mount, because it will then + not be unmounted from the namespace when the namespace dies. */ + flatpak_bwrap_add_args_data_fd (bwrap, "--file", glnx_steal_fd (&app_info_fd), "/.flatpak-info"); + + if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error)) + return FALSE; + + return TRUE; +} + +static gboolean +start_dbus_proxy (FlatpakBwrap *app_bwrap, + FlatpakBwrap *proxy_arg_bwrap, + const char *app_info_path, + GError **error) +{ + char x = 'x'; + const char *proxy; + g_autofree char *commandline = NULL; + g_autoptr(FlatpakBwrap) proxy_bwrap = NULL; + int sync_fds[2] = {-1, -1}; + int proxy_start_index; + g_auto(GStrv) minimal_envp = NULL; + + minimal_envp = flatpak_run_get_minimal_env (FALSE, FALSE); + proxy_bwrap = flatpak_bwrap_new (NULL); + + if (!add_bwrap_wrapper (proxy_bwrap, app_info_path, error)) + return FALSE; + + proxy = g_getenv ("FLATPAK_DBUSPROXY"); + if (proxy == NULL) + proxy = DBUSPROXY; + + flatpak_bwrap_add_arg (proxy_bwrap, proxy); + + proxy_start_index = proxy_bwrap->argv->len; + + if (pipe2 (sync_fds, O_CLOEXEC) < 0) + { + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + _("Unable to create sync pipe")); + return FALSE; + } + + /* read end goes to app */ + flatpak_bwrap_add_args_data_fd (app_bwrap, "--sync-fd", sync_fds[0], NULL); + + /* write end goes to proxy */ + flatpak_bwrap_add_fd (proxy_bwrap, sync_fds[1]); + flatpak_bwrap_add_arg_printf (proxy_bwrap, "--fd=%d", sync_fds[1]); + + /* Note: This steals the fds from proxy_arg_bwrap */ + flatpak_bwrap_append_bwrap (proxy_bwrap, proxy_arg_bwrap); + + if (!flatpak_bwrap_bundle_args (proxy_bwrap, proxy_start_index, -1, TRUE, error)) + return FALSE; + + flatpak_bwrap_finish (proxy_bwrap); + + commandline = flatpak_quote_argv ((const char **) proxy_bwrap->argv->pdata, -1); + g_debug ("Running '%s'", commandline); + + if (!g_spawn_async (NULL, + (char **) proxy_bwrap->argv->pdata, + NULL, + G_SPAWN_SEARCH_PATH, + flatpak_bwrap_child_setup_cb, proxy_bwrap->fds, + NULL, error)) + return FALSE; + + /* Sync with proxy, i.e. wait until its listening on the sockets */ + if (read (sync_fds[0], &x, 1) != 1) + { + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + _("Failed to sync with dbus proxy")); + return FALSE; + } + + return TRUE; +} + static int flatpak_extension_compare_by_path (gconstpointer _a, gconstpointer _b) @@ -759,22 +982,12 @@ GCancellable *cancellable, GError **error) { - gboolean unrestricted_session_bus; - gboolean unrestricted_system_bus; g_autoptr(GError) my_error = NULL; g_autoptr(FlatpakExports) exports = NULL; - g_autoptr(GPtrArray) session_bus_proxy_argv = NULL; - g_autoptr(GPtrArray) system_bus_proxy_argv = NULL; - g_autoptr(GPtrArray) a11y_bus_proxy_argv = NULL; - int sync_fds[2] = {-1, -1}; + g_autoptr(FlatpakBwrap) proxy_arg_bwrap = flatpak_bwrap_new (flatpak_bwrap_empty_env); gboolean has_wayland = FALSE; gboolean allow_x11 = FALSE; - if ((flags & FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY) == 0) - session_bus_proxy_argv = g_ptr_array_new_with_free_func (g_free); - if ((flags & FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY) == 0) - system_bus_proxy_argv = g_ptr_array_new_with_free_func (g_free); - if ((context->shares & FLATPAK_CONTEXT_SHARED_IPC) == 0) { g_debug ("Disallowing ipc access"); @@ -850,95 +1063,9 @@ flatpak_run_add_pulseaudio_args (bwrap); } - unrestricted_session_bus = (context->sockets & FLATPAK_CONTEXT_SOCKET_SESSION_BUS) != 0; - if (unrestricted_session_bus) - g_debug ("Allowing session-dbus access"); - if (flatpak_run_add_session_dbus_args (bwrap, session_bus_proxy_argv, unrestricted_session_bus) && - !unrestricted_session_bus && session_bus_proxy_argv) - flatpak_context_add_bus_filters (context, app_id, TRUE, session_bus_proxy_argv); - - unrestricted_system_bus = (context->sockets & FLATPAK_CONTEXT_SOCKET_SYSTEM_BUS) != 0; - if (unrestricted_system_bus) - g_debug ("Allowing system-dbus access"); - if (flatpak_run_add_system_dbus_args (context, bwrap, system_bus_proxy_argv, - unrestricted_system_bus) && - !unrestricted_system_bus && system_bus_proxy_argv) - flatpak_context_add_bus_filters (context, app_id, FALSE, system_bus_proxy_argv); - - if ((flags & FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY) == 0) - { - g_autoptr(GDBusConnection) session_bus = NULL; - g_autofree char *a11y_address = NULL; - - session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); - if (session_bus) - { - g_autoptr(GError) local_error = NULL; - g_autoptr(GDBusMessage) reply = NULL; - g_autoptr(GDBusMessage) msg = - g_dbus_message_new_method_call ("org.a11y.Bus", - "/org/a11y/bus", - "org.a11y.Bus", - "GetAddress"); - g_dbus_message_set_body (msg, g_variant_new ("()")); - reply = - g_dbus_connection_send_message_with_reply_sync (session_bus, msg, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, - 30000, - NULL, - NULL, - NULL); - if (reply) - { - if (g_dbus_message_to_gerror (reply, &local_error)) - { - if (!g_error_matches (local_error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) - g_message ("Can't find a11y bus: %s", local_error->message); - } - else - { - g_variant_get (g_dbus_message_get_body (reply), - "(s)", &a11y_address); - } - } - } - - if (a11y_address) - { - g_autofree char *proxy_socket = create_proxy_socket ("a11y-bus-proxy-XXXXXX"); - if (proxy_socket) - { - g_autofree char *sandbox_socket_path = g_strdup_printf ("/run/user/%d/at-spi-bus", getuid ()); - g_autofree char *sandbox_dbus_address = g_strdup_printf ("unix:path=/run/user/%d/at-spi-bus", getuid ()); - - a11y_bus_proxy_argv = g_ptr_array_new_with_free_func (g_free); - - g_ptr_array_add (a11y_bus_proxy_argv, g_strdup (a11y_address)); - g_ptr_array_add (a11y_bus_proxy_argv, g_strdup (proxy_socket)); - g_ptr_array_add (a11y_bus_proxy_argv, g_strdup ("--filter")); - g_ptr_array_add (a11y_bus_proxy_argv, g_strdup ("--sloppy-names")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.Socket.Embed@/org/a11y/atspi/accessible/root")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.Socket.Unembed@/org/a11y/atspi/accessible/root")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.Registry.GetRegisteredEvents@/org/a11y/atspi/registry")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.GetKeystrokeListeners@/org/a11y/atspi/registry/deviceeventcontroller")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.GetDeviceEventListeners@/org/a11y/atspi/registry/deviceeventcontroller")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.NotifyListenersSync@/org/a11y/atspi/registry/deviceeventcontroller")); - g_ptr_array_add (a11y_bus_proxy_argv, - g_strdup ("--filter=org.a11y.atspi.Registry=org.a11y.atspi.DeviceEventController.NotifyListenersAsync@/org/a11y/atspi/registry/deviceeventcontroller")); - - flatpak_bwrap_add_args (bwrap, - "--bind", proxy_socket, sandbox_socket_path, - NULL); - flatpak_bwrap_set_env (bwrap, "AT_SPI_BUS_ADDRESS", sandbox_dbus_address, TRUE); - } - } - } + flatpak_run_add_session_dbus_args (bwrap, proxy_arg_bwrap, context, flags, app_id); + flatpak_run_add_system_dbus_args (bwrap, proxy_arg_bwrap, context, flags); + flatpak_run_add_a11y_dbus_args (bwrap, proxy_arg_bwrap, context, flags); if (g_environ_getenv (bwrap->envp, "LD_LIBRARY_PATH") != NULL) { @@ -959,16 +1086,10 @@ g_clear_error (&my_error); } - if (!add_dbus_proxy_args (bwrap->argv, - session_bus_proxy_argv, (flags & FLATPAK_RUN_FLAG_LOG_SESSION_BUS) != 0, - system_bus_proxy_argv, (flags & FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS) != 0, - a11y_bus_proxy_argv, (flags & FLATPAK_RUN_FLAG_LOG_A11Y_BUS) != 0, - sync_fds, app_info_path, error)) + if (!flatpak_bwrap_is_empty (proxy_arg_bwrap) && + !start_dbus_proxy (bwrap, proxy_arg_bwrap, app_info_path, error)) return FALSE; - if (sync_fds[1] != -1) - close (sync_fds[1]); - if (exports_out) *exports_out = g_steal_pointer (&exports); @@ -1229,10 +1350,10 @@ GVariant *properties = NULL; GVariant *aux = NULL; guint32 pid; - GMainContext *main_context = NULL; GMainLoop *main_loop = NULL; struct JobData data; gboolean res = FALSE; + g_autoptr(GMainContextPopDefault) main_context = NULL; path = g_strdup_printf ("/run/user/%d/systemd/private", getuid ()); @@ -1240,11 +1361,9 @@ return flatpak_fail (error, "No systemd user session available, cgroups not available"); - main_context = g_main_context_new (); + main_context = flatpak_main_context_new_default (); main_loop = g_main_loop_new (main_context, FALSE); - g_main_context_push_thread_default (main_context); - address = g_strconcat ("unix:path=", path, NULL); conn = g_dbus_connection_new_for_address_sync (address, @@ -1296,11 +1415,6 @@ res = TRUE; out: - if (main_context) - { - g_main_context_pop_thread_default (main_context); - g_main_context_unref (main_context); - } if (main_loop) g_main_loop_unref (main_loop); if (manager) @@ -1396,14 +1510,6 @@ } } -static void -add_default_permissions (FlatpakContext *app_context) -{ - flatpak_context_set_session_bus_policy (app_context, - "org.freedesktop.portal.*", - FLATPAK_POLICY_TALK); -} - FlatpakContext * flatpak_app_compute_permissions (GKeyFile *app_metadata, GKeyFile *runtime_metadata, @@ -1413,8 +1519,6 @@ app_context = flatpak_context_new (); - add_default_permissions (app_context); - if (runtime_metadata != NULL && !flatpak_context_load_metadata (app_context, runtime_metadata, error)) return NULL; @@ -1426,6 +1530,96 @@ return g_steal_pointer (&app_context); } +static void +flatpak_run_gc_ids (void) +{ + g_autofree char *base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL); + g_auto(GLnxDirFdIterator) iter = { 0 }; + struct dirent *dent; + + /* Clean up unused instances */ + if (!glnx_dirfd_iterator_init_at (AT_FDCWD, base_dir, FALSE, &iter, NULL)) + return; + + 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 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 && + 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); + } + } + } +} + +static char * +flatpak_run_allocate_id (int *lock_fd_out) +{ + g_autofree char *base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL); + int count; + + g_mkdir_with_parents (base_dir, 0755); + + flatpak_run_gc_ids (); + + for (count = 0; count < 1000; count++) + { + g_autofree char *instance_id = NULL; + g_autofree char *instance_dir = NULL; + + instance_id = g_strdup_printf ("%u", g_random_int ()); + + instance_dir = g_build_filename (base_dir, instance_id, NULL); + + /* We use an atomic mkdir to ensure the instance id is unique */ + if (mkdir (instance_dir, 0755) == 0) + { + g_autofree char *lock_file = g_build_filename (instance_dir, ".ref", NULL); + glnx_autofd int lock_fd = -1; + struct flock l = { + .l_type = F_RDLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 + }; + + /* Then we take a file lock inside the dir, hold that during + * setup and in bwrap. Anyone trying to clean up unused + * directories need to first verify that there is a .ref + * file and take a write lock on .ref to ensure its not in + * use. */ + lock_fd = open (lock_file, O_RDWR | O_CREAT | O_CLOEXEC, 0644); + if (lock_fd != -1 && fcntl (lock_fd, F_SETLK, &l) == 0) + { + *lock_fd_out = glnx_steal_fd (&lock_fd); + g_debug ("Allocated instance id %s", instance_id); + return g_steal_pointer (&instance_id); + } + } + } + + return NULL; +} + gboolean flatpak_run_add_app_info_args (FlatpakBwrap *bwrap, GFile *app_files, @@ -1452,6 +1646,29 @@ g_autofree char *old_dest = g_strdup_printf ("/run/user/%d/flatpak-info", getuid ()); g_auto(GStrv) runtime_ref_parts = g_strsplit (runtime_ref, "/", 0); const char *group; + g_autofree char *instance_id = NULL; + glnx_autofd int lock_fd = -1; + g_autofree char *instance_id_host_dir = NULL; + g_autofree char *instance_id_sandbox_dir = NULL; + g_autofree char *instance_id_lock_file = NULL; + + instance_id = flatpak_run_allocate_id (&lock_fd); + if (instance_id == NULL) + return flatpak_fail (error, "Unable to allocate instance id"); + + instance_id_host_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", instance_id, NULL); + instance_id_sandbox_dir = g_strdup_printf ("/run/user/%d/.flatpak/%s", getuid (), instance_id); + instance_id_lock_file = g_build_filename (instance_id_sandbox_dir, ".ref", NULL); + + flatpak_bwrap_add_args (bwrap, + "--ro-bind", + instance_id_host_dir, + instance_id_sandbox_dir, + "--lock-file", + instance_id_lock_file, + NULL); + /* Keep the .ref lock held until we've started bwrap to avoid races */ + flatpak_bwrap_add_noinherit_fd (bwrap, glnx_steal_fd (&lock_fd)); fd = g_file_open_tmp ("flatpak-context-XXXXXX", &tmp_path, NULL); if (fd < 0) @@ -1475,6 +1692,8 @@ g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_RUNTIME, runtime_ref); + g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_INSTANCE, + FLATPAK_METADATA_KEY_INSTANCE_ID, instance_id); if (app_id_dir) { g_autofree char *instance_path = g_file_get_path (app_id_dir); @@ -1597,6 +1816,8 @@ { g_autoptr(AutoFlatpakSessionHelper) session_helper = NULL; g_autofree char *monitor_path = NULL; + g_autofree char *pkcs11_socket_path = NULL; + g_autoptr(GVariant) session_data = NULL; if (use_session_helper) { @@ -1609,17 +1830,36 @@ } if (session_helper && - flatpak_session_helper_call_request_monitor_sync (session_helper, - &monitor_path, + flatpak_session_helper_call_request_session_sync (session_helper, + &session_data, NULL, NULL)) { - flatpak_bwrap_add_args (bwrap, - "--ro-bind", monitor_path, "/run/host/monitor", - "--symlink", "/run/host/monitor/localtime", "/etc/localtime", - "--symlink", "/run/host/monitor/resolv.conf", "/etc/resolv.conf", - "--symlink", "/run/host/monitor/host.conf", "/etc/host.conf", - "--symlink", "/run/host/monitor/hosts", "/etc/hosts", - NULL); + if (g_variant_lookup (session_data, "path", "s", &monitor_path)) + flatpak_bwrap_add_args (bwrap, + "--ro-bind", monitor_path, "/run/host/monitor", + "--symlink", "/run/host/monitor/localtime", "/etc/localtime", + "--symlink", "/run/host/monitor/resolv.conf", "/etc/resolv.conf", + "--symlink", "/run/host/monitor/host.conf", "/etc/host.conf", + "--symlink", "/run/host/monitor/hosts", "/etc/hosts", + NULL); + + if (g_variant_lookup (session_data, "pkcs11-socket", "s", &pkcs11_socket_path)) + { + g_autofree char *sandbox_pkcs11_socket_path = g_strdup_printf ("/run/user/%d/p11-kit/pkcs11", getuid ()); + const char *trusted_module_contents = + "# This overrides the runtime p11-kit-trusted module with a client one talking to the trust module on the host\n" + "module: p11-kit-client.so\n"; + + if (flatpak_bwrap_add_args_data (bwrap, "p11-kit-trust.module", + trusted_module_contents, -1, + "/etc/pkcs11/modules/p11-kit-trust.module", NULL)) + { + flatpak_bwrap_add_args (bwrap, + "--ro-bind", pkcs11_socket_path, sandbox_pkcs11_socket_path, + NULL); + flatpak_bwrap_unset_env (bwrap, "P11_KIT_SERVER_ADDRESS"); + } + } } else { @@ -1732,255 +1972,6 @@ *out_mount_path = g_steal_pointer (&doc_mount_path); } -static gchar * -join_args (GPtrArray *argv_array, gsize *len_out) -{ - gchar *string; - gchar *ptr; - gint i; - gsize len = 0; - - for (i = 0; i < argv_array->len && argv_array->pdata[i] != NULL; i++) - len += strlen (argv_array->pdata[i]) + 1; - - string = g_new (gchar, len); - *string = 0; - ptr = string; - for (i = 0; i < argv_array->len && argv_array->pdata[i] != NULL; i++) - ptr = g_stpcpy (ptr, argv_array->pdata[i]) + 1; - - *len_out = len; - return string; -} - -typedef struct { - int sync_fd; - int app_info_fd; - int bwrap_args_fd; -} DbusProxySpawnData; - -static void -dbus_spawn_child_setup (gpointer user_data) -{ - DbusProxySpawnData *data = user_data; - - /* Unset CLOEXEC */ - fcntl (data->sync_fd, F_SETFD, 0); - fcntl (data->app_info_fd, F_SETFD, 0); - fcntl (data->bwrap_args_fd, F_SETFD, 0); -} - -/* This wraps the argv in a bwrap call, primary to allow the - command to be run with a proper /.flatpak-info with data - taken from app_info_fd */ -static gboolean -prepend_bwrap_argv_wrapper (GPtrArray *argv, - int app_info_fd, - int *bwrap_fd_out, - GError **error) -{ - int i = 0; - g_auto(GLnxDirFdIterator) dir_iter = { 0 }; - struct dirent *dent; - g_autoptr(GPtrArray) bwrap_args = g_ptr_array_new_with_free_func (g_free); - gsize bwrap_args_len; - g_auto(GLnxTmpfile) args_tmpf = { 0, }; - g_autofree char *bwrap_args_data = NULL; - g_autofree char *proxy_socket_dir = g_build_filename (g_get_user_runtime_dir (), ".dbus-proxy/", NULL); - - if (!glnx_dirfd_iterator_init_at (AT_FDCWD, "/", FALSE, &dir_iter, error)) - return FALSE; - - while (TRUE) - { - if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dir_iter, &dent, NULL, error)) - return FALSE; - - if (dent == NULL) - break; - - if (strcmp (dent->d_name, ".flatpak-info") == 0) - continue; - - if (dent->d_type == DT_DIR) - { - if (strcmp (dent->d_name, "tmp") == 0 || - strcmp (dent->d_name, "var") == 0 || - strcmp (dent->d_name, "run") == 0) - g_ptr_array_add (bwrap_args, g_strdup ("--bind")); - else - g_ptr_array_add (bwrap_args, g_strdup ("--ro-bind")); - g_ptr_array_add (bwrap_args, g_strconcat ("/", dent->d_name, NULL)); - g_ptr_array_add (bwrap_args, g_strconcat ("/", dent->d_name, NULL)); - } - else if (dent->d_type == DT_LNK) - { - ssize_t symlink_size; - char path_buffer[PATH_MAX + 1]; - - symlink_size = readlinkat (dir_iter.fd, dent->d_name, path_buffer, sizeof (path_buffer) - 1); - if (symlink_size < 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - path_buffer[symlink_size] = 0; - - g_ptr_array_add (bwrap_args, g_strdup ("--symlink")); - g_ptr_array_add (bwrap_args, g_strdup (path_buffer)); - g_ptr_array_add (bwrap_args, g_strconcat ("/", dent->d_name, NULL)); - } - } - - g_ptr_array_add (bwrap_args, g_strdup ("--bind")); - g_ptr_array_add (bwrap_args, g_strdup (proxy_socket_dir)); - g_ptr_array_add (bwrap_args, g_strdup (proxy_socket_dir)); - - /* This is a file rather than a bind mount, because it will then - not be unmounted from the namespace when the namespace dies. */ - g_ptr_array_add (bwrap_args, g_strdup ("--file")); - g_ptr_array_add (bwrap_args, g_strdup_printf ("%d", app_info_fd)); - g_ptr_array_add (bwrap_args, g_strdup ("/.flatpak-info")); - g_ptr_array_add (bwrap_args, NULL); - - { - g_autofree char *commandline = flatpak_quote_argv ((const char **) bwrap_args->pdata); - flatpak_debug2 ("bwrap args '%s'", commandline); - } - - bwrap_args_data = join_args (bwrap_args, &bwrap_args_len); - if (!flatpak_buffer_to_sealed_memfd_or_tmpfile (&args_tmpf, "bwrap-args", bwrap_args_data, bwrap_args_len, error)) - return FALSE; - - g_ptr_array_insert (argv, i++, g_strdup (flatpak_get_bwrap ())); - g_ptr_array_insert (argv, i++, g_strdup ("--args")); - g_ptr_array_insert (argv, i++, g_strdup_printf ("%d", args_tmpf.fd)); - - *bwrap_fd_out = glnx_steal_fd (&args_tmpf.fd); - return TRUE; -} - -static gboolean -has_args (GPtrArray *args) -{ - return args != NULL && args->len > 0; -} - -static void -append_proxy_args (GPtrArray *dbus_proxy_argv, - GPtrArray *args, - gboolean enable_logging) -{ - if (has_args (args)) - { - int i; - - for (i = 0; i < args->len; i++) - g_ptr_array_add (dbus_proxy_argv, g_strdup (args->pdata[i])); - - if (enable_logging) - g_ptr_array_add (dbus_proxy_argv, g_strdup ("--log")); - } -} - -static gboolean -add_dbus_proxy_args (GPtrArray *argv_array, - GPtrArray *session_dbus_proxy_argv, - gboolean enable_session_logging, - GPtrArray *system_dbus_proxy_argv, - gboolean enable_system_logging, - GPtrArray *a11y_dbus_proxy_argv, - gboolean enable_a11y_logging, - int sync_fds[2], - const char *app_info_path, - GError **error) -{ - char x = 'x'; - const char *proxy; - g_autofree char *commandline = NULL; - DbusProxySpawnData spawn_data; - glnx_autofd int app_info_fd = -1; - glnx_autofd int bwrap_args_fd = -1; - g_autoptr(GPtrArray) dbus_proxy_argv = NULL; - - if (!has_args (session_dbus_proxy_argv) && - !has_args (system_dbus_proxy_argv) && - !has_args (a11y_dbus_proxy_argv)) - return TRUE; - - if (sync_fds[0] == -1) - { - access ("sync_fds", 0); - if (pipe (sync_fds) < 0) - { - g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), - _("Unable to create sync pipe")); - return FALSE; - } - - add_args_data_fd (argv_array, NULL, - "--sync-fd", sync_fds[0], NULL); - } - - proxy = g_getenv ("FLATPAK_DBUSPROXY"); - if (proxy == NULL) - proxy = DBUSPROXY; - - dbus_proxy_argv = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (dbus_proxy_argv, g_strdup (proxy)); - g_ptr_array_add (dbus_proxy_argv, g_strdup_printf ("--fd=%d", sync_fds[1])); - - append_proxy_args (dbus_proxy_argv, session_dbus_proxy_argv, enable_session_logging); - append_proxy_args (dbus_proxy_argv, system_dbus_proxy_argv, enable_system_logging); - append_proxy_args (dbus_proxy_argv, a11y_dbus_proxy_argv, enable_a11y_logging); - - g_ptr_array_add (dbus_proxy_argv, NULL); /* NULL terminate */ - - app_info_fd = open (app_info_path, O_RDONLY); - if (app_info_fd == -1) - { - int errsv = errno; - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Failed to open app info file: %s"), g_strerror (errsv)); - return FALSE; - } - - if (!prepend_bwrap_argv_wrapper (dbus_proxy_argv, app_info_fd, &bwrap_args_fd, error)) - return FALSE; - - commandline = flatpak_quote_argv ((const char **) dbus_proxy_argv->pdata); - flatpak_debug2 ("Running '%s'", commandline); - - spawn_data.sync_fd = sync_fds[1]; - spawn_data.app_info_fd = app_info_fd; - spawn_data.bwrap_args_fd = bwrap_args_fd; - if (!g_spawn_async (NULL, - (char **) dbus_proxy_argv->pdata, - NULL, - G_SPAWN_SEARCH_PATH, - dbus_spawn_child_setup, - &spawn_data, - NULL, error)) - { - close (sync_fds[0]); - close (sync_fds[1]); - return FALSE; - } - - /* Sync with proxy, i.e. wait until its listening on the sockets */ - if (read (sync_fds[0], &x, 1) != 1) - { - g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), - _("Failed to sync with dbus proxy")); - - close (sync_fds[0]); - close (sync_fds[1]); - return FALSE; - } - - return TRUE; -} - #ifdef ENABLE_SECCOMP static const uint32_t seccomp_x86_64_extra_arches[] = { SCMP_ARCH_X86, 0, }; @@ -2001,10 +1992,11 @@ setup_seccomp (FlatpakBwrap *bwrap, const char *arch, gulong allowed_personality, - gboolean multiarch, - gboolean devel, + FlatpakRunFlags run_flags, GError **error) { + gboolean multiarch = (run_flags & FLATPAK_RUN_FLAG_MULTIARCH) != 0; + gboolean devel = (run_flags & FLATPAK_RUN_FLAG_DEVEL) != 0; __attribute__((cleanup (cleanup_seccomp))) scmp_filter_ctx seccomp = NULL; /**** BEGIN NOTE ON CODE SHARING @@ -2089,21 +2081,19 @@ {SCMP_SYS (ptrace)} }; /* Blacklist all but unix, inet, inet6 and netlink */ - int socket_family_blacklist[] = { - AF_AX25, - AF_IPX, - AF_APPLETALK, - AF_NETROM, - AF_BRIDGE, - AF_ATMPVC, - AF_X25, - AF_ROSE, - AF_DECnet, - AF_NETBEUI, - AF_SECURITY, - AF_KEY, - AF_NETLINK + 1, /* Last gets CMP_GE, so order is important */ + struct { + int family; + FlatpakRunFlags flags_mask; + } socket_family_whitelist[] = { + /* NOTE: Keep in numerical order */ + { AF_UNSPEC, 0 }, + { AF_LOCAL, 0 }, + { AF_INET, 0 }, + { AF_INET6, 0 }, + { AF_NETLINK, 0 }, + { AF_BLUETOOTH, FLATPAK_RUN_FLAG_BLUETOOTH }, }; + int last_allowed_family; int i, r; g_auto(GLnxTmpfile) seccomp_tmpf = { 0, }; @@ -2197,14 +2187,25 @@ /* Socket filtering doesn't work on e.g. i386, so ignore failures here * However, we need to user seccomp_rule_add_exact to avoid libseccomp doing * something else: https://github.com/seccomp/libseccomp/issues/8 */ - for (i = 0; i < G_N_ELEMENTS (socket_family_blacklist); i++) + last_allowed_family = -1; + for (i = 0; i < G_N_ELEMENTS (socket_family_whitelist); i++) { - int family = socket_family_blacklist[i]; - if (i == G_N_ELEMENTS (socket_family_blacklist) - 1) - seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_GE, family)); - else - seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_EQ, family)); + int family = socket_family_whitelist[i].family; + int disallowed; + + if (socket_family_whitelist[i].flags_mask != 0 && + (socket_family_whitelist[i].flags_mask & run_flags) != socket_family_whitelist[i].flags_mask) + continue; + + for (disallowed = last_allowed_family + 1; disallowed < family; disallowed++) + { + /* Blacklist the in-between valid families */ + seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_EQ, disallowed)); + } + last_allowed_family = family; } + /* Blacklist the rest */ + seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_GE, last_allowed_family + 1)); if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &seccomp_tmpf, error)) return FALSE; @@ -2257,6 +2258,7 @@ g_autofree char *run_dir = g_strdup_printf ("/run/user/%d", getuid ()); g_autofree char *passwd_contents = NULL; g_autofree char *group_contents = NULL; + const char *pkcs11_conf_contents = NULL; struct group *g = getgrgid (getgid ()); gulong pers; @@ -2275,6 +2277,10 @@ g->gr_name, getgid (), g_get_user_name ()); + pkcs11_conf_contents = + "# Disable user pkcs11 config, because the host modules don't work in the runtime\n" + "user-config: none\n"; + flatpak_bwrap_add_args (bwrap, "--unshare-pid", "--proc", "/proc", @@ -2308,6 +2314,9 @@ if (!flatpak_bwrap_add_args_data (bwrap, "group", group_contents, -1, "/etc/group", error)) return FALSE; + if (!flatpak_bwrap_add_args_data (bwrap, "pkcs11.conf", pkcs11_conf_contents, -1, "/etc/pkcs11/pkcs11.conf", error)) + return FALSE; + if (g_file_test ("/etc/machine-id", G_FILE_TEST_EXISTS)) flatpak_bwrap_add_args (bwrap, "--ro-bind", "/etc/machine-id", "/etc/machine-id", NULL); else if (g_file_test ("/var/lib/dbus/machine-id", G_FILE_TEST_EXISTS)) @@ -2341,7 +2350,8 @@ strcmp (dent->d_name, "resolv.conf") == 0 || strcmp (dent->d_name, "host.conf") == 0 || strcmp (dent->d_name, "hosts") == 0 || - strcmp (dent->d_name, "localtime") == 0) + strcmp (dent->d_name, "localtime") == 0 || + strcmp (dent->d_name, "pkcs11") == 0) continue; src = g_build_filename (flatpak_file_get_path_cached (etc), dent->d_name, NULL); @@ -2395,12 +2405,7 @@ personality (pers); #ifdef ENABLE_SECCOMP - if (!setup_seccomp (bwrap, - arch, - pers, - (flags & FLATPAK_RUN_FLAG_MULTIARCH) != 0, - (flags & FLATPAK_RUN_FLAG_DEVEL) != 0, - error)) + if (!setup_seccomp (bwrap, arch, pers, flags, error)) return FALSE; #endif @@ -2410,31 +2415,6 @@ return TRUE; } -/* Unset FD_CLOEXEC on the array of fds passed in @user_data */ -static void -child_setup (gpointer user_data) -{ - GArray *fd_array = user_data; - int i; - - /* If no fd_array was specified, don't care. */ - if (fd_array == NULL) - return; - - /* Otherwise, mark not - close-on-exec all the fds in the array */ - for (i = 0; i < fd_array->len; i++) - { - int fd = g_array_index (fd_array, int, i); - - /* We also seek all fds to the start, because this lets - us use the same fd_array multiple times */ - if (lseek (fd, 0, SEEK_SET) < 0) - g_printerr ("lseek error in child setup"); - - fcntl (fd, F_SETFD, 0); - } -} - static gboolean forward_file (XdpDbusDocuments *documents, const char *app_id, @@ -2480,14 +2460,14 @@ } static gboolean -add_rest_args (const char *app_id, +add_rest_args (FlatpakBwrap *bwrap, + const char *app_id, FlatpakExports *exports, - gboolean file_forwarding, - const char *doc_mount_path, - GPtrArray *argv_array, - char *args[], - int n_args, - GError **error) + gboolean file_forwarding, + const char *doc_mount_path, + char *args[], + int n_args, + GError **error) { g_autoptr(XdpDbusDocuments) documents = NULL; gboolean forwarding = FALSE; @@ -2547,7 +2527,7 @@ { g_autofree char *doc_id = NULL; g_autofree char *basename = NULL; - char *doc_path; + g_autofree char *doc_path = NULL; if (!forward_file (documents, app_id, flatpak_file_get_path_cached (file), &doc_id, error)) return FALSE; @@ -2564,10 +2544,10 @@ } g_debug ("Forwarding file '%s' as '%s' to %s", args[i], doc_path, app_id); - g_ptr_array_add (argv_array, doc_path); + flatpak_bwrap_add_arg (bwrap, doc_path); } else - g_ptr_array_add (argv_array, g_strdup (args[i])); + flatpak_bwrap_add_arg (bwrap, args[i]); } return TRUE; @@ -2682,7 +2662,6 @@ minimal_envp = flatpak_run_get_minimal_env (FALSE, FALSE); bwrap = flatpak_bwrap_new (minimal_envp); - flatpak_bwrap_add_args (bwrap, flatpak_get_bwrap (), NULL); flatpak_bwrap_append_args (bwrap, base_argv_array); @@ -2707,12 +2686,18 @@ "--proc", "/proc", "--dev", "/dev", "--bind", flatpak_file_get_path_cached (ld_so_dir), "/run/ld-so-cache-dir", + NULL); + + if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error)) + return -1; + + flatpak_bwrap_add_args (bwrap, "ldconfig", "-X", "-C", sandbox_cache_path, NULL); - g_ptr_array_add (bwrap->argv, NULL); + flatpak_bwrap_finish (bwrap); - commandline = flatpak_quote_argv ((const char **) bwrap->argv->pdata); - flatpak_debug2 ("Running: '%s'", commandline); + commandline = flatpak_quote_argv ((const char **) bwrap->argv->pdata, -1); + g_debug ("Running: '%s'", commandline); combined_fd_array = g_array_new (FALSE, TRUE, sizeof (int)); g_array_append_vals (combined_fd_array, base_fd_array->data, base_fd_array->len); @@ -2722,7 +2707,7 @@ (char **) bwrap->argv->pdata, bwrap->envp, G_SPAWN_SEARCH_PATH, - child_setup, combined_fd_array, + flatpak_bwrap_child_setup_cb, combined_fd_array, NULL, NULL, &exit_status, error)) @@ -2789,8 +2774,6 @@ g_autoptr(GKeyFile) metakey = NULL; g_autoptr(GKeyFile) runtime_metakey = NULL; g_autoptr(FlatpakBwrap) bwrap = NULL; - g_auto(GLnxTmpfile) arg_tmpf = { 0, }; - g_autoptr(GPtrArray) real_argv_array = NULL; const char *command = "/bin/sh"; g_autoptr(GError) my_error = NULL; g_auto(GStrv) runtime_parts = NULL; @@ -2801,8 +2784,6 @@ g_autoptr(FlatpakExports) exports = NULL; g_auto(GStrv) app_ref_parts = NULL; g_autofree char *commandline = NULL; - int commandline_2_start; - g_autofree char *commandline2 = NULL; g_autofree char *doc_mount_path = NULL; g_autofree char *app_extensions = NULL; g_autofree char *runtime_extensions = NULL; @@ -2820,6 +2801,7 @@ return FALSE; bwrap = flatpak_bwrap_new (NULL); + flatpak_bwrap_add_arg (bwrap, flatpak_get_bwrap ()); if (app_deploy == NULL) { @@ -2971,24 +2953,20 @@ if (use_ld_so_cache) { checksum = calculate_ld_cache_checksum (app_deploy_data, runtime_deploy_data, - app_extensions, runtime_extensions); + app_extensions, runtime_extensions); ld_so_fd = regenerate_ld_cache (bwrap->argv, - bwrap->fds, - app_id_dir, - checksum, - runtime_files, - generate_ld_so_conf, - cancellable, error); + bwrap->fds, + app_id_dir, + checksum, + runtime_files, + generate_ld_so_conf, + cancellable, error); if (ld_so_fd == -1) - return FALSE; - g_array_append_val (bwrap->fds, ld_so_fd); + return FALSE; + flatpak_bwrap_add_fd (bwrap, ld_so_fd); } - if (flatpak_context_allows_features (app_context, FLATPAK_CONTEXT_FEATURE_DEVEL)) - flags |= FLATPAK_RUN_FLAG_DEVEL; - - if (flatpak_context_allows_features (app_context, FLATPAK_CONTEXT_FEATURE_MULTIARCH)) - flags |= FLATPAK_RUN_FLAG_MULTIARCH; + flags |= flatpak_context_get_run_flags (app_context); if (!flatpak_run_setup_base_argv (bwrap, runtime_files, app_id_dir, app_ref_parts[2], flags, error)) return FALSE; @@ -3002,7 +2980,9 @@ if (ld_so_fd != -1) { /* Don't add to fd_array, its already there */ - add_args_data_fd (bwrap->argv, NULL, "--ro-bind-data", ld_so_fd, "/etc/ld.so.cache"); + flatpak_bwrap_add_arg (bwrap, "--ro-bind-data"); + flatpak_bwrap_add_arg_printf (bwrap, "%d", ld_so_fd); + flatpak_bwrap_add_arg (bwrap, "/etc/ld.so.cache"); } if (!flatpak_run_add_app_info_args (bwrap, @@ -3049,42 +3029,29 @@ command = default_command; } - real_argv_array = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (real_argv_array, g_strdup (flatpak_get_bwrap ())); - - { - gsize len; - g_autofree char *args = join_args (bwrap->argv, &len); - - if (!flatpak_buffer_to_sealed_memfd_or_tmpfile (&arg_tmpf, "bwrap-args", args, len, error)) - return FALSE; - - add_args_data_fd (real_argv_array, bwrap->fds, - "--args", glnx_steal_fd (&arg_tmpf.fd), NULL); - } + if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error)) + return FALSE; - commandline_2_start = real_argv_array->len; + flatpak_bwrap_add_arg (bwrap, command); - g_ptr_array_add (real_argv_array, g_strdup (command)); - if (!add_rest_args (app_ref_parts[1], exports, (flags & FLATPAK_RUN_FLAG_FILE_FORWARDING) != 0, + if (!add_rest_args (bwrap, app_ref_parts[1], + exports, (flags & FLATPAK_RUN_FLAG_FILE_FORWARDING) != 0, doc_mount_path, - real_argv_array, args, n_args, error)) + args, n_args, error)) return FALSE; - g_ptr_array_add (real_argv_array, NULL); - g_ptr_array_add (bwrap->argv, NULL); + flatpak_bwrap_finish (bwrap); - commandline = flatpak_quote_argv ((const char **) bwrap->argv->pdata); - commandline2 = flatpak_quote_argv (((const char **) real_argv_array->pdata) + commandline_2_start); - flatpak_debug2 ("Running '%s %s'", commandline, commandline2); + commandline = flatpak_quote_argv ((const char **) bwrap->argv->pdata, -1); + g_debug ("Running '%s'", commandline); if ((flags & FLATPAK_RUN_FLAG_BACKGROUND) != 0) { if (!g_spawn_async (NULL, - (char **) real_argv_array->pdata, + (char **) bwrap->argv->pdata, bwrap->envp, G_SPAWN_SEARCH_PATH, - child_setup, bwrap->fds, + flatpak_bwrap_child_setup_cb, bwrap->fds, NULL, error)) return FALSE; @@ -3092,8 +3059,8 @@ else { /* Ensure we unset O_CLOEXEC */ - child_setup (bwrap->fds); - if (execvpe (flatpak_get_bwrap (), (char **) real_argv_array->pdata, bwrap->envp) == -1) + flatpak_bwrap_child_setup_cb (bwrap->fds); + if (execvpe (flatpak_get_bwrap (), (char **) bwrap->argv->pdata, bwrap->envp) == -1) { g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), _("Unable to start app")); diff -Nru flatpak-0.11.7/common/flatpak-run.h flatpak-0.11.8.3/common/flatpak-run.h --- flatpak-0.11.7/common/flatpak-run.h 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-run.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,194 +0,0 @@ -/* - * Copyright © 2014 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_RUN_H__ -#define __FLATPAK_RUN_H__ - -#include "libglnx/libglnx.h" -#include "flatpak-common-types.h" -#include "flatpak-context.h" -#include "flatpak-bwrap.h" -#include "flatpak-utils.h" -#include "flatpak-exports.h" - -gboolean flatpak_run_in_transient_unit (const char *app_id, - GError **error); - -/* See flatpak-metadata(5) */ - -#define FLATPAK_METADATA_GROUP_APPLICATION "Application" -#define FLATPAK_METADATA_GROUP_RUNTIME "Runtime" -#define FLATPAK_METADATA_KEY_COMMAND "command" -#define FLATPAK_METADATA_KEY_NAME "name" -#define FLATPAK_METADATA_KEY_REQUIRED_FLATPAK "required-flatpak" -#define FLATPAK_METADATA_KEY_RUNTIME "runtime" -#define FLATPAK_METADATA_KEY_SDK "sdk" -#define FLATPAK_METADATA_KEY_TAGS "tags" - -#define FLATPAK_METADATA_GROUP_CONTEXT "Context" -#define FLATPAK_METADATA_KEY_SHARED "shared" -#define FLATPAK_METADATA_KEY_SOCKETS "sockets" -#define FLATPAK_METADATA_KEY_FILESYSTEMS "filesystems" -#define FLATPAK_METADATA_KEY_PERSISTENT "persistent" -#define FLATPAK_METADATA_KEY_DEVICES "devices" -#define FLATPAK_METADATA_KEY_FEATURES "features" - -#define FLATPAK_METADATA_GROUP_INSTANCE "Instance" -#define FLATPAK_METADATA_KEY_INSTANCE_PATH "instance-path" -#define FLATPAK_METADATA_KEY_APP_PATH "app-path" -#define FLATPAK_METADATA_KEY_APP_COMMIT "app-commit" -#define FLATPAK_METADATA_KEY_APP_EXTENSIONS "app-extensions" -#define FLATPAK_METADATA_KEY_ARCH "arch" -#define FLATPAK_METADATA_KEY_BRANCH "branch" -#define FLATPAK_METADATA_KEY_FLATPAK_VERSION "flatpak-version" -#define FLATPAK_METADATA_KEY_RUNTIME_PATH "runtime-path" -#define FLATPAK_METADATA_KEY_RUNTIME_COMMIT "runtime-commit" -#define FLATPAK_METADATA_KEY_RUNTIME_EXTENSIONS "runtime-extensions" -#define FLATPAK_METADATA_KEY_SESSION_BUS_PROXY "session-bus-proxy" -#define FLATPAK_METADATA_KEY_SYSTEM_BUS_PROXY "system-bus-proxy" -#define FLATPAK_METADATA_KEY_EXTRA_ARGS "extra-args" -#define FLATPAK_METADATA_KEY_SANDBOX "sandbox" -#define FLATPAK_METADATA_KEY_BUILD "build" - -#define FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY "Session Bus Policy" -#define FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY "System Bus Policy" -#define FLATPAK_METADATA_GROUP_PREFIX_POLICY "Policy " -#define FLATPAK_METADATA_GROUP_ENVIRONMENT "Environment" - -#define FLATPAK_METADATA_GROUP_PREFIX_EXTENSION "Extension " -#define FLATPAK_METADATA_KEY_ADD_LD_PATH "add-ld-path" -#define FLATPAK_METADATA_KEY_AUTODELETE "autodelete" -#define FLATPAK_METADATA_KEY_DIRECTORY "directory" -#define FLATPAK_METADATA_KEY_DOWNLOAD_IF "download-if" -#define FLATPAK_METADATA_KEY_ENABLE_IF "enable-if" -#define FLATPAK_METADATA_KEY_MERGE_DIRS "merge-dirs" -#define FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD "no-autodownload" -#define FLATPAK_METADATA_KEY_SUBDIRECTORIES "subdirectories" -#define FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX "subdirectory-suffix" -#define FLATPAK_METADATA_KEY_LOCALE_SUBSET "locale-subset" -#define FLATPAK_METADATA_KEY_VERSION "version" -#define FLATPAK_METADATA_KEY_VERSIONS "versions" - -#ifdef FLATPAK_ENABLE_P2P -#define FLATPAK_METADATA_KEY_COLLECTION_ID "collection-id" -#endif /* FLATPAK_ENABLE_P2P */ - -#define FLATPAK_METADATA_GROUP_EXTRA_DATA "Extra Data" -#define FLATPAK_METADATA_KEY_EXTRA_DATA_CHECKSUM "checksum" -#define FLATPAK_METADATA_KEY_EXTRA_DATA_INSTALLED_SIZE "installed-size" -#define FLATPAK_METADATA_KEY_EXTRA_DATA_NAME "name" -#define FLATPAK_METADATA_KEY_EXTRA_DATA_SIZE "size" -#define FLATPAK_METADATA_KEY_EXTRA_DATA_URI "uri" -#define FLATPAK_METADATA_KEY_NO_RUNTIME "NoRuntime" - -#define FLATPAK_METADATA_GROUP_EXTENSION_OF "ExtensionOf" -#define FLATPAK_METADATA_KEY_PRIORITY "priority" -#define FLATPAK_METADATA_KEY_REF "ref" -#define FLATPAK_METADATA_KEY_TAG "tag" - - -typedef enum { - FLATPAK_RUN_FLAG_DEVEL = (1 << 0), - FLATPAK_RUN_FLAG_BACKGROUND = (1 << 1), - FLATPAK_RUN_FLAG_LOG_SESSION_BUS = (1 << 2), - FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS = (1 << 3), - FLATPAK_RUN_FLAG_NO_SESSION_HELPER = (1 << 4), - FLATPAK_RUN_FLAG_MULTIARCH = (1 << 5), - FLATPAK_RUN_FLAG_WRITABLE_ETC = (1 << 6), - FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY = (1 << 7), - FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY = (1 << 8), - FLATPAK_RUN_FLAG_SET_PERSONALITY = (1 << 9), - FLATPAK_RUN_FLAG_FILE_FORWARDING = (1 << 10), - FLATPAK_RUN_FLAG_DIE_WITH_PARENT = (1 << 11), - FLATPAK_RUN_FLAG_LOG_A11Y_BUS = (1 << 12), - FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY = (1 << 13), - FLATPAK_RUN_FLAG_SANDBOX = (1 << 14), - FLATPAK_RUN_FLAG_NO_DOCUMENTS_PORTAL = (1 << 15), -} FlatpakRunFlags; - -gboolean flatpak_run_add_extension_args (FlatpakBwrap *bwrap, - GKeyFile *metakey, - const char *full_ref, - gboolean use_ld_so_cache, - char **extensions_out, - GCancellable *cancellable, - GError **error); -gboolean flatpak_run_add_environment_args (FlatpakBwrap *bwrap, - const char *app_info_path, - FlatpakRunFlags flags, - const char *app_id, - FlatpakContext *context, - GFile *app_id_dir, - FlatpakExports **exports_out, - GCancellable *cancellable, - GError **error); -char ** flatpak_run_get_minimal_env (gboolean devel, gboolean use_ld_so_cache); -void flatpak_run_apply_env_default (FlatpakBwrap *bwrap, gboolean use_ld_so_cache); -void flatpak_run_apply_env_appid (FlatpakBwrap *bwrap, - GFile *app_dir); -void flatpak_run_apply_env_vars (FlatpakBwrap *bwrap, - FlatpakContext *context); -FlatpakContext *flatpak_app_compute_permissions (GKeyFile *app_metadata, - GKeyFile *runtime_metadata, - GError **error); -GFile *flatpak_get_data_dir (const char *app_id); -GFile *flatpak_ensure_data_dir (const char *app_id, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, - GFile *runtime_files, - GFile *app_id_dir, - const char *arch, - FlatpakRunFlags flags, - GError **error); -gboolean flatpak_run_add_app_info_args (FlatpakBwrap *bwrap, - GFile *app_files, - GVariant *app_deploy_data, - const char *app_extensions, - GFile *runtime_files, - GVariant *runtime_deploy_data, - const char *runtime_extensions, - const char *app_id, - const char *app_branch, - const char *runtime_ref, - GFile *app_id_dir, - FlatpakContext *final_app_context, - FlatpakContext *cmdline_context, - gboolean sandbox, - gboolean build, - char **app_info_path_out, - GError **error); - -gboolean flatpak_run_app (const char *app_ref, - FlatpakDeploy *app_deploy, - FlatpakContext *extra_context, - const char *custom_runtime, - const char *custom_runtime_version, - const char *custom_runtime_commit, - FlatpakRunFlags flags, - const char *custom_command, - char *args[], - int n_args, - GCancellable *cancellable, - GError **error); - - -#endif /* __FLATPAK_RUN_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-run-private.h flatpak-0.11.8.3/common/flatpak-run-private.h --- flatpak-0.11.7/common/flatpak-run-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-run-private.h 2018-06-11 15:40:17.000000000 +0100 @@ -0,0 +1,176 @@ +/* + * Copyright © 2014 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_RUN_H__ +#define __FLATPAK_RUN_H__ + +#include "libglnx/libglnx.h" +#include "flatpak-common-types-private.h" +#include "flatpak-context-private.h" +#include "flatpak-bwrap-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-exports-private.h" + +gboolean flatpak_run_in_transient_unit (const char *app_id, + GError **error); + +/* See flatpak-metadata(5) */ + +#define FLATPAK_METADATA_GROUP_APPLICATION "Application" +#define FLATPAK_METADATA_GROUP_RUNTIME "Runtime" +#define FLATPAK_METADATA_KEY_COMMAND "command" +#define FLATPAK_METADATA_KEY_NAME "name" +#define FLATPAK_METADATA_KEY_REQUIRED_FLATPAK "required-flatpak" +#define FLATPAK_METADATA_KEY_RUNTIME "runtime" +#define FLATPAK_METADATA_KEY_SDK "sdk" +#define FLATPAK_METADATA_KEY_TAGS "tags" + +#define FLATPAK_METADATA_GROUP_CONTEXT "Context" +#define FLATPAK_METADATA_KEY_SHARED "shared" +#define FLATPAK_METADATA_KEY_SOCKETS "sockets" +#define FLATPAK_METADATA_KEY_FILESYSTEMS "filesystems" +#define FLATPAK_METADATA_KEY_PERSISTENT "persistent" +#define FLATPAK_METADATA_KEY_DEVICES "devices" +#define FLATPAK_METADATA_KEY_FEATURES "features" + +#define FLATPAK_METADATA_GROUP_INSTANCE "Instance" +#define FLATPAK_METADATA_KEY_INSTANCE_PATH "instance-path" +#define FLATPAK_METADATA_KEY_INSTANCE_ID "instance-id" +#define FLATPAK_METADATA_KEY_APP_PATH "app-path" +#define FLATPAK_METADATA_KEY_APP_COMMIT "app-commit" +#define FLATPAK_METADATA_KEY_APP_EXTENSIONS "app-extensions" +#define FLATPAK_METADATA_KEY_ARCH "arch" +#define FLATPAK_METADATA_KEY_BRANCH "branch" +#define FLATPAK_METADATA_KEY_FLATPAK_VERSION "flatpak-version" +#define FLATPAK_METADATA_KEY_RUNTIME_PATH "runtime-path" +#define FLATPAK_METADATA_KEY_RUNTIME_COMMIT "runtime-commit" +#define FLATPAK_METADATA_KEY_RUNTIME_EXTENSIONS "runtime-extensions" +#define FLATPAK_METADATA_KEY_SESSION_BUS_PROXY "session-bus-proxy" +#define FLATPAK_METADATA_KEY_SYSTEM_BUS_PROXY "system-bus-proxy" +#define FLATPAK_METADATA_KEY_EXTRA_ARGS "extra-args" +#define FLATPAK_METADATA_KEY_SANDBOX "sandbox" +#define FLATPAK_METADATA_KEY_BUILD "build" + +#define FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY "Session Bus Policy" +#define FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY "System Bus Policy" +#define FLATPAK_METADATA_GROUP_PREFIX_POLICY "Policy " +#define FLATPAK_METADATA_GROUP_ENVIRONMENT "Environment" + +#define FLATPAK_METADATA_GROUP_PREFIX_EXTENSION "Extension " +#define FLATPAK_METADATA_KEY_ADD_LD_PATH "add-ld-path" +#define FLATPAK_METADATA_KEY_AUTODELETE "autodelete" +#define FLATPAK_METADATA_KEY_DIRECTORY "directory" +#define FLATPAK_METADATA_KEY_DOWNLOAD_IF "download-if" +#define FLATPAK_METADATA_KEY_ENABLE_IF "enable-if" +#define FLATPAK_METADATA_KEY_AUTOPRUNE_UNLESS "autoprune-unless" +#define FLATPAK_METADATA_KEY_MERGE_DIRS "merge-dirs" +#define FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD "no-autodownload" +#define FLATPAK_METADATA_KEY_SUBDIRECTORIES "subdirectories" +#define FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX "subdirectory-suffix" +#define FLATPAK_METADATA_KEY_LOCALE_SUBSET "locale-subset" +#define FLATPAK_METADATA_KEY_VERSION "version" +#define FLATPAK_METADATA_KEY_VERSIONS "versions" + +#ifdef FLATPAK_ENABLE_P2P +#define FLATPAK_METADATA_KEY_COLLECTION_ID "collection-id" +#endif /* FLATPAK_ENABLE_P2P */ + +#define FLATPAK_METADATA_GROUP_EXTRA_DATA "Extra Data" +#define FLATPAK_METADATA_KEY_EXTRA_DATA_CHECKSUM "checksum" +#define FLATPAK_METADATA_KEY_EXTRA_DATA_INSTALLED_SIZE "installed-size" +#define FLATPAK_METADATA_KEY_EXTRA_DATA_NAME "name" +#define FLATPAK_METADATA_KEY_EXTRA_DATA_SIZE "size" +#define FLATPAK_METADATA_KEY_EXTRA_DATA_URI "uri" +#define FLATPAK_METADATA_KEY_NO_RUNTIME "NoRuntime" + +#define FLATPAK_METADATA_GROUP_EXTENSION_OF "ExtensionOf" +#define FLATPAK_METADATA_KEY_PRIORITY "priority" +#define FLATPAK_METADATA_KEY_REF "ref" +#define FLATPAK_METADATA_KEY_TAG "tag" + +gboolean flatpak_run_add_extension_args (FlatpakBwrap *bwrap, + GKeyFile *metakey, + const char *full_ref, + gboolean use_ld_so_cache, + char **extensions_out, + GCancellable *cancellable, + GError **error); +gboolean flatpak_run_add_environment_args (FlatpakBwrap *bwrap, + const char *app_info_path, + FlatpakRunFlags flags, + const char *app_id, + FlatpakContext *context, + GFile *app_id_dir, + FlatpakExports **exports_out, + GCancellable *cancellable, + GError **error); +char ** flatpak_run_get_minimal_env (gboolean devel, gboolean use_ld_so_cache); +void flatpak_run_apply_env_default (FlatpakBwrap *bwrap, gboolean use_ld_so_cache); +void flatpak_run_apply_env_appid (FlatpakBwrap *bwrap, + GFile *app_dir); +void flatpak_run_apply_env_vars (FlatpakBwrap *bwrap, + FlatpakContext *context); +FlatpakContext *flatpak_app_compute_permissions (GKeyFile *app_metadata, + GKeyFile *runtime_metadata, + GError **error); +GFile *flatpak_get_data_dir (const char *app_id); +GFile *flatpak_ensure_data_dir (const char *app_id, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_run_setup_base_argv (FlatpakBwrap *bwrap, + GFile *runtime_files, + GFile *app_id_dir, + const char *arch, + FlatpakRunFlags flags, + GError **error); +gboolean flatpak_run_add_app_info_args (FlatpakBwrap *bwrap, + GFile *app_files, + GVariant *app_deploy_data, + const char *app_extensions, + GFile *runtime_files, + GVariant *runtime_deploy_data, + const char *runtime_extensions, + const char *app_id, + const char *app_branch, + const char *runtime_ref, + GFile *app_id_dir, + FlatpakContext *final_app_context, + FlatpakContext *cmdline_context, + gboolean sandbox, + gboolean build, + char **app_info_path_out, + GError **error); + +gboolean flatpak_run_app (const char *app_ref, + FlatpakDeploy *app_deploy, + FlatpakContext *extra_context, + const char *custom_runtime, + const char *custom_runtime_version, + const char *custom_runtime_commit, + FlatpakRunFlags flags, + const char *custom_command, + char *args[], + int n_args, + GCancellable *cancellable, + GError **error); + + +#endif /* __FLATPAK_RUN_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-table-printer.c flatpak-0.11.8.3/common/flatpak-table-printer.c --- flatpak-0.11.7/common/flatpak-table-printer.c 2018-04-12 15:09:07.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-table-printer.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,258 +0,0 @@ -/* - * Copyright © 2014 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 . - * - * Authors: - * Alexander Larsson - */ - -#include "config.h" - -#include "flatpak-table-printer.h" -#include "flatpak-utils.h" - -#include -#include -#include -#include - - -typedef struct { - char *text; - int align; -} Cell; - -static void -free_cell (gpointer data) -{ - Cell *cell = data; - - g_free (cell->text); - g_free (cell); -} - -struct FlatpakTablePrinter -{ - GPtrArray *titles; - GPtrArray *rows; - GPtrArray *current; - int n_columns; -}; - -FlatpakTablePrinter * -flatpak_table_printer_new (void) -{ - FlatpakTablePrinter *printer = g_new0 (FlatpakTablePrinter, 1); - - printer->titles = g_ptr_array_new_with_free_func (g_free); - printer->rows = g_ptr_array_new_with_free_func ((GDestroyNotify) g_ptr_array_unref); - printer->current = g_ptr_array_new_with_free_func (free_cell); - - return printer; -} - -void -flatpak_table_printer_free (FlatpakTablePrinter *printer) -{ - g_ptr_array_free (printer->titles, TRUE); - g_ptr_array_free (printer->rows, TRUE); - g_ptr_array_free (printer->current, TRUE); - g_free (printer); -} - -void -flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer, - int column, - const char *text) -{ - g_ptr_array_insert (printer->titles, column, g_strdup (text)); -} - -void -flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer, - const char *text, - int align) -{ - Cell *cell = g_new (Cell, 1); - cell->text = text ? g_strdup (text) : g_strdup (""); - cell->align = align; - g_ptr_array_add (printer->current, cell); -} - -static const char * -find_decimal_point (const char *text) -{ - struct lconv *locale_data; - - locale_data = localeconv (); - return strstr (text, locale_data->decimal_point); -} - -void -flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer, - const char *text) -{ - const char *decimal; - int align = -1; - - decimal = find_decimal_point (text); - if (decimal) - align = decimal - text; - - flatpak_table_printer_add_aligned_column (printer, text, align); -} - -void -flatpak_table_printer_add_column (FlatpakTablePrinter *printer, - const char *text) -{ - flatpak_table_printer_add_aligned_column (printer, text, -1); -} - -void -flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer, - const char *text, - gsize len) -{ - Cell *cell = g_new (Cell, 1); - cell->text = text ? g_strndup (text, len) : g_strdup (""); - cell->align = -1; - g_ptr_array_add (printer->current, cell); -} - -void -flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer, - const char *text) -{ - Cell *cell; - char *new; - - g_assert (printer->current->len > 0); - - cell = g_ptr_array_index (printer->current, printer->current->len - 1); - - if (cell->text[0] != 0) - new = g_strconcat (cell->text, ",", text, NULL); - else - new = g_strdup (text); - - g_free (cell->text); - cell->text = new; -} - -void -flatpak_table_printer_append_with_comma_printf (FlatpakTablePrinter *printer, - const char *format, - ...) -{ - va_list var_args; - g_autofree char *s = NULL; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" - va_start (var_args, format); - s = g_strdup_vprintf (format, var_args); - va_end (var_args); -#pragma GCC diagnostic pop - - flatpak_table_printer_append_with_comma (printer, s); -} - -void -flatpak_table_printer_finish_row (FlatpakTablePrinter *printer) -{ - if (printer->current->len == 0) - return; /* Ignore empty rows */ - - printer->n_columns = MAX (printer->n_columns, printer->current->len); - g_ptr_array_add (printer->rows, printer->current); - printer->current = g_ptr_array_new_with_free_func (free_cell); -} - -void -flatpak_table_printer_print (FlatpakTablePrinter *printer) -{ - g_autofree int *widths = NULL; - g_autofree int *lwidths = NULL; - g_autofree int *rwidths = NULL; - int i, j; - - if (printer->current->len != 0) - flatpak_table_printer_finish_row (printer); - - widths = g_new0 (int, printer->n_columns); - lwidths = g_new0 (int, printer->n_columns); - rwidths = g_new0 (int, printer->n_columns); - - for (i = 0; i < printer->titles->len && i < printer->n_columns; i++) - { - char *title = g_ptr_array_index (printer->titles, i); - - if (title) - widths[i] = MAX (widths[i], strlen (title)); - } - - for (i = 0; i < printer->rows->len; i++) - { - GPtrArray *row = g_ptr_array_index (printer->rows, i); - - for (j = 0; j < row->len; j++) - { - Cell *cell = g_ptr_array_index (row, j); - int width; - - width = strlen (cell->text); - widths[j] = MAX (widths[j], width); - if (cell->align >= 0) - { - lwidths[j] = MAX (lwidths[j], cell->align); - rwidths[j] = MAX (rwidths[j], width - cell->align); - } - } - } - - if (flatpak_fancy_output () && printer->titles->len > 0) - { - g_print (FLATPAK_ANSI_BOLD_ON); - for (i = 0; i < printer->titles->len && i < printer->n_columns; i++) - { - char *title = g_ptr_array_index (printer->titles, i); - - g_print ("%s%-*s", (i == 0) ? "" : " ", widths[i], title); - } - g_print (FLATPAK_ANSI_BOLD_OFF); - g_print ("\n"); - } - - for (i = 0; i < printer->rows->len; i++) - { - GPtrArray *row = g_ptr_array_index (printer->rows, i); - - for (j = 0; j < row->len; j++) - { - Cell *cell = g_ptr_array_index (row, j); - if (flatpak_fancy_output ()) - { - if (cell->align < 0) - g_print ("%s%-*s", (j == 0) ? "" : " ", widths[j], cell->text); - else - g_print ("%s%*s%-*s", (j == 0) ? "" : " ", lwidths[j] - cell->align, "", widths[j] - (lwidths[j] - cell->align), cell->text); - } - else - g_print ("%s%s", cell->text, (j < row->len - 1) ? "\t" : ""); - } - g_print ("\n"); - } -} diff -Nru flatpak-0.11.7/common/flatpak-table-printer.h flatpak-0.11.8.3/common/flatpak-table-printer.h --- flatpak-0.11.7/common/flatpak-table-printer.h 2018-04-12 15:09:07.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-table-printer.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,51 +0,0 @@ -/* - * Copyright © 2014 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_TABLE_PRINTER_H__ -#define __FLATPAK_TABLE_PRINTER_H__ - -#include - -typedef struct FlatpakTablePrinter FlatpakTablePrinter; - -FlatpakTablePrinter *flatpak_table_printer_new (void); -void flatpak_table_printer_free (FlatpakTablePrinter *printer); -void flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer, - int column, - const char *title); -void flatpak_table_printer_add_column (FlatpakTablePrinter *printer, - const char *text); -void flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer, - const char *text, - int align); -void flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer, - const char *text); -void flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer, - const char *text, - gsize len); -void flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer, - const char *text); -void flatpak_table_printer_append_with_comma_printf (FlatpakTablePrinter *printer, - const char *format, - ...); -void flatpak_table_printer_finish_row (FlatpakTablePrinter *printer); -void flatpak_table_printer_print (FlatpakTablePrinter *printer); - -#endif /* __FLATPAK_TABLE_PRINTER_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-transaction.c flatpak-0.11.8.3/common/flatpak-transaction.c --- flatpak-0.11.7/common/flatpak-transaction.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-transaction.c 2018-06-13 09:26:30.000000000 +0100 @@ -0,0 +1,1575 @@ +/* + * Copyright © 2016 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 . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include +#include + +#include "flatpak-transaction-private.h" +#include "flatpak-installation-private.h" +#include "flatpak-utils-private.h" +#include "flatpak-error.h" + +/** + * SECTION:flatpak-transaction + * @Title: FlatpakTransaction + * @Short_description: Transaction information + * + * FlatpakTransaction is an object representing an install/update + * transaction. You create an object like this using flatpak_transaction_new_for_installation() + * and then you add all the operations (installs, updates, etc) you wish to do. Then + * you start the transaction with flatpak_transaction_run() which will resolve all kinds + * of dependencies and report progress and status while downloading and installing these. + * + * A transaction is a blocking operation, and all signals are emitted in the same thread. + * This means you should either handle the signals directly (say, by doing blocking console + * interaction, or by just returning without interaction), or run the operation in a separate + * thread and do your own forwarding to the GUI thread. + */ + +typedef struct FlatpakTransactionOp FlatpakTransactionOp; + +typedef enum { + FLATPAK_TRANSACTION_OP_KIND_INSTALL, + FLATPAK_TRANSACTION_OP_KIND_UPDATE, + FLATPAK_TRANSACTION_OP_KIND_BUNDLE, + FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE, + FLATPAK_TRANSACTION_OP_KIND_UNINSTALL, +} FlatpakTransactionOpKind; + +struct FlatpakTransactionOp { + char *remote; + char *ref; + /* NULL means unspecified (normally keep whatever was there before), [] means force everything */ + char **subpaths; + char *commit; + GFile *bundle; + FlatpakTransactionOpKind kind; + gboolean non_fatal; + FlatpakTransactionOp *source_op; /* This is the main app/runtime ref for related extensions, and the runtime for apps */ + gboolean failed; +}; + +typedef struct _FlatpakTransactionPrivate FlatpakTransactionPrivate; + +struct _FlatpakTransactionPrivate { + GObject parent; + + FlatpakInstallation *installation; + FlatpakDir *dir; + GHashTable *last_op_for_ref; + GHashTable *remote_states; /* (element-type utf8 FlatpakRemoteState) */ + GPtrArray *system_dirs; + GList *ops; + GPtrArray *added_origin_remotes; + + gboolean no_pull; + gboolean no_deploy; + gboolean disable_static_deltas; + gboolean disable_prune; + gboolean disable_deps; + gboolean disable_related; + gboolean reinstall; + gboolean force_uninstall; +}; + +enum { + NEW_OPERATION, + OPERATION_DONE, + OPERATION_ERROR, + CHOOSE_REMOTE_FOR_REF, + END_OF_LIFED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_INSTALLATION, +}; + +struct _FlatpakTransactionProgress { + GObject parent; + + OstreeAsyncProgress *ostree_progress; + char *status; + gboolean estimating; + int progress; + + gboolean done; +}; + +enum { + CHANGED, + LAST_PROGRESS_SIGNAL +}; + +static guint progress_signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (FlatpakTransactionProgress, flatpak_transaction_progress, G_TYPE_OBJECT) + +void +flatpak_transaction_progress_set_update_frequency (FlatpakTransactionProgress *self, + guint update_frequency) +{ + g_object_set_data (G_OBJECT (self->ostree_progress), "update-frequency", GUINT_TO_POINTER (update_frequency)); +} + + +char * +flatpak_transaction_progress_get_status (FlatpakTransactionProgress *self) +{ + return g_strdup (self->status); +} + +gboolean +flatpak_transaction_progress_get_is_estimating (FlatpakTransactionProgress *self) +{ + return self->estimating; +} + +int +flatpak_transaction_progress_get_progress (FlatpakTransactionProgress *self) +{ + return self->progress; +} + +static void +flatpak_transaction_progress_finalize (GObject *object) +{ + FlatpakTransactionProgress *self = (FlatpakTransactionProgress *) object; + + g_free (self->status); + g_object_unref (self->ostree_progress); + + G_OBJECT_CLASS (flatpak_transaction_progress_parent_class)->finalize (object); +} + +static void +flatpak_transaction_progress_class_init (FlatpakTransactionProgressClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = flatpak_transaction_progress_finalize; + + /** + * FlatpakTransactionProgress::changed: + * @object: A #FlatpakTransactionProgress + * + * Emitted when some detail of the progress object changes, you can call the various methods to get the current status. + */ + progress_signals[CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0); +} + +static void +got_progress_cb (const char *status, + guint progress, + gboolean estimating, + gpointer user_data) +{ + FlatpakTransactionProgress *p = user_data; + + g_free (p->status); + p->status = g_strdup (status); + p->progress = progress; + p->estimating = estimating; + + if (!p->done) + g_signal_emit (p, progress_signals[CHANGED], 0); +} + +static void +flatpak_transaction_progress_init (FlatpakTransactionProgress *self) +{ + self->status = g_strdup ("Initializing"); + self->estimating = TRUE; + self->ostree_progress = flatpak_progress_new (got_progress_cb, self); +} + +static void +flatpak_transaction_progress_done (FlatpakTransactionProgress *self) +{ + ostree_async_progress_finish (self->ostree_progress); + self->done = TRUE; +} + +static FlatpakTransactionProgress * +flatpak_transaction_progress_new (void) +{ + return g_object_new (FLATPAK_TYPE_TRANSACTION_PROGRESS, NULL); +} + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void initable_iface_init (GInitableIface *initable_iface); + +G_DEFINE_TYPE_WITH_CODE (FlatpakTransaction, flatpak_transaction, G_TYPE_OBJECT, + G_ADD_PRIVATE(FlatpakTransaction) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)) + +static FlatpakTransactionOperationType +op_type_from_resolved_kind (FlatpakTransactionOpKind kind) +{ + switch (kind) + { + case FLATPAK_TRANSACTION_OP_KIND_INSTALL: + return FLATPAK_TRANSACTION_OPERATION_INSTALL; + case FLATPAK_TRANSACTION_OP_KIND_UPDATE: + return FLATPAK_TRANSACTION_OPERATION_UPDATE; + case FLATPAK_TRANSACTION_OP_KIND_BUNDLE: + return FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE; + case FLATPAK_TRANSACTION_OP_KIND_UNINSTALL: + return FLATPAK_TRANSACTION_OPERATION_UNINSTALL; + + /* This should be resolve before converting to type */ + case FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE: + default: + g_assert_not_reached (); + } +} + +static gboolean +transaction_is_local_only (FlatpakTransaction *self, + FlatpakTransactionOpKind kind) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + return priv->no_pull || kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL; +} + +static gboolean +remote_name_is_file (const char *remote_name) +{ + return remote_name != NULL && + g_str_has_prefix (remote_name, "file://"); +} + +/* Check if the ref is in the dir, or in the system dir, in case its a + * user-dir or another system-wide installation. We want to avoid depending + * on user-installed things when installing to the system dir. + */ +static gboolean +ref_is_installed (FlatpakTransaction *self, + const char *ref, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autoptr(GFile) deploy_dir = NULL; + FlatpakDir *dir = priv->dir; + int i; + + deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, NULL); + if (deploy_dir != NULL) + return TRUE; + + /* Don't try to fallback for the system's default directory. */ + if (!flatpak_dir_is_user (dir) && flatpak_dir_get_id (dir) == NULL) + return FALSE; + + /* Lazy initialization of this, once per transaction */ + if (priv->system_dirs == NULL) + { + priv->system_dirs = flatpak_dir_get_system_list (NULL, error); + if (priv->system_dirs == NULL) + return FALSE; + } + + for (i = 0; i < priv->system_dirs->len; i++) + { + FlatpakDir *system_dir = g_ptr_array_index (priv->system_dirs, i); + + if (g_strcmp0 (flatpak_dir_get_id (dir), flatpak_dir_get_id (system_dir)) == 0) + continue; + + deploy_dir = flatpak_dir_get_if_deployed (system_dir, ref, NULL, NULL); + if (deploy_dir != NULL) + return TRUE; + } + + return FALSE; +} + +static gboolean +dir_ref_is_installed (FlatpakDir *dir, const char *ref, char **remote_out, GVariant **deploy_data_out) +{ + g_autoptr(GVariant) deploy_data = NULL; + + deploy_data = flatpak_dir_get_deploy_data (dir, ref, NULL, NULL); + if (deploy_data == NULL) + return FALSE; + + if (remote_out) + *remote_out = g_strdup (flatpak_deploy_data_get_origin (deploy_data)); + + if (deploy_data_out) + *deploy_data_out = g_variant_ref (deploy_data); + + return TRUE; +} + +static FlatpakTransactionOp * +flatpak_transaction_operation_new (const char *remote, + const char *ref, + const char **subpaths, + const char *commit, + GFile *bundle, + FlatpakTransactionOpKind kind) +{ + FlatpakTransactionOp *self = g_new0 (FlatpakTransactionOp, 1); + + self->remote = g_strdup (remote); + self->ref = g_strdup (ref); + self->subpaths = g_strdupv ((char **)subpaths); + self->commit = g_strdup (commit); + if (bundle) + self->bundle = g_object_ref (bundle); + self->kind = kind; + + return self; +} + +static void +flatpak_transaction_operation_free (FlatpakTransactionOp *self) +{ + g_free (self->remote); + g_free (self->ref); + g_free (self->commit); + g_strfreev (self->subpaths); + g_clear_object (&self->bundle); + g_free (self); +} + +gboolean +flatpak_transaction_is_empty (FlatpakTransaction *self) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + return priv->ops == NULL; +} + +static void +flatpak_transaction_finalize (GObject *object) +{ + FlatpakTransaction *self = (FlatpakTransaction *) object; + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + g_clear_object (&priv->installation); + + g_hash_table_unref (priv->last_op_for_ref); + g_hash_table_unref (priv->remote_states); + g_list_free_full (priv->ops, (GDestroyNotify)flatpak_transaction_operation_free); + g_object_unref (priv->dir); + + g_ptr_array_unref (priv->added_origin_remotes); + + if (priv->system_dirs != NULL) + g_ptr_array_free (priv->system_dirs, TRUE); + + G_OBJECT_CLASS (flatpak_transaction_parent_class)->finalize (object); +} + +static void +flatpak_transaction_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakTransaction *self = FLATPAK_TRANSACTION (object); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + switch (prop_id) + { + case PROP_INSTALLATION: + g_clear_object (&priv->installation); + priv->installation = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_transaction_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakTransaction *self = FLATPAK_TRANSACTION (object); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + switch (prop_id) + { + case PROP_INSTALLATION: + g_value_set_object (value, priv->installation); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_transaction_class_init (FlatpakTransactionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = flatpak_transaction_finalize; + object_class->get_property = flatpak_transaction_get_property; + object_class->set_property = flatpak_transaction_set_property; + + g_object_class_install_property (object_class, + PROP_INSTALLATION, + g_param_spec_object ("installation", + "Installation", + "The installation instance", + FLATPAK_TYPE_INSTALLATION, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); + + /** + * FlatpakTransaction::new-operation: + * @object: A #FlatpakTransaction + * @ref: The ref the operation will be working on + * @remote: The ref the operation will be working on + * @bundle: The bundle path (or %NULL) + * @operation_type: A #FlatpakTransactionOperationType specifying operation type + * @progress: A #FlatpakTransactionProgress + */ + signals[NEW_OPERATION] = + g_signal_new ("new-operation", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FlatpakTransactionClass, new_operation), + NULL, NULL, + NULL, + G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, FLATPAK_TYPE_TRANSACTION_PROGRESS); + + /** + * FlatpakTransaction::operation-error: + * @object: A #FlatpakTransaction + * @ref: The ref the operation was working on + * @remote: The remote + * @operation_type: A #FlatpakTransactionOperationType specifying operation type + * @error: A #GError + * @details: A #FlatpakTransactionErrorDetails with Details about the error + * + * Returns: the %TRUE to contine transaction, %FALSE to stop + */ + signals[OPERATION_ERROR] = + g_signal_new ("operation-error", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FlatpakTransactionClass, operation_error), + NULL, NULL, + NULL, + G_TYPE_BOOLEAN, 5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_ERROR, G_TYPE_INT); + + /** + * FlatpakTransaction::operation-done: + * @object: A #FlatpakTransaction + * @ref: The ref the operation was working on + * @remote: The remote + * @operation_type: A #FlatpakTransactionOperationType specifying operation type + * @commit: The new commit checksum + * @result: A #FlatpakTransactionResult giving details about the result + * + */ + signals[OPERATION_DONE] = + g_signal_new ("operation-done", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FlatpakTransactionClass, operation_done), + NULL, NULL, + NULL, + G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); + + /** + * FlatpakTransaction::choose-remote-for-ref: + * @object: A #FlatpakTransaction + * @for_ref: The ref we are installing + * @runtime_ref: The ref we are looking for + * @remotes: the remotes that has the ref, sorted in prio order + * + * Returns: the index of the remote to use, or -1 to not pick one (and fail) + */ + signals[CHOOSE_REMOTE_FOR_REF] = + g_signal_new ("choose-remote-for-ref", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FlatpakTransactionClass, choose_remote_for_ref), + NULL, NULL, + NULL, + G_TYPE_INT, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRV); + /** + * FlatpakTransaction::end-of-lifed: + * @object: A #FlatpakTransaction + * @ref: The ref we are installing + * @reason: The eol reason, or %NULL + * @rebase: The new name, if rebased, or %NULL + */ + signals[END_OF_LIFED] = + g_signal_new ("end-of-lifed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FlatpakTransactionClass, end_of_lifed), + NULL, NULL, + NULL, + G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); +} + +static void +flatpak_transaction_init (FlatpakTransaction *self) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + priv->last_op_for_ref = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + priv->remote_states = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)flatpak_remote_state_free); + priv->added_origin_remotes = g_ptr_array_new_with_free_func (g_free); +} + + +static gboolean +initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + FlatpakTransaction *self = FLATPAK_TRANSACTION (initable); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autoptr(FlatpakDir) dir = NULL; + + if (priv->installation == NULL) + return flatpak_fail (error, "No installation specified"); + + dir = flatpak_installation_clone_dir (priv->installation, cancellable, error); + if (dir == NULL) + return FALSE; + + priv->dir = g_steal_pointer (&dir); + + return TRUE; +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_iface->init = initable_init; +} + +/** + * flatpak_transaction_new_for_installation: + * @installation: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakTransaction object that can be used to do installation + * and updates of multiple refs, as well as their dependencies, in a single + * operation. Set the options you want on the transaction and add the + * refs you want to install/update, then start the transaction with + * flatpak_transaction_run (). + * + * Returns: (transfer full): a #FlatpakTransaction, or %NULL on failure. + */ +FlatpakTransaction * +flatpak_transaction_new_for_installation (FlatpakInstallation *installation, + GCancellable *cancellable, + GError **error) +{ + return g_initable_new (FLATPAK_TYPE_TRANSACTION, + cancellable, error, + "installation", installation, + NULL); +} + +void +flatpak_transaction_set_no_pull (FlatpakTransaction *self, + gboolean no_pull) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + priv->no_pull = no_pull; +} + +void +flatpak_transaction_set_no_deploy (FlatpakTransaction *self, + gboolean no_deploy) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->no_deploy = no_deploy; +} + +void +flatpak_transaction_set_disable_static_deltas (FlatpakTransaction *self, + gboolean disable_static_deltas) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->disable_static_deltas = disable_static_deltas; +} + +void +flatpak_transaction_set_disable_prune (FlatpakTransaction *self, + gboolean disable_prune) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->disable_prune = disable_prune; +} + +void +flatpak_transaction_set_disable_dependencies (FlatpakTransaction *self, + gboolean disable_dependencies) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->disable_deps = disable_dependencies; +} + +void +flatpak_transaction_set_disable_related (FlatpakTransaction *self, + gboolean disable_related) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->disable_related = disable_related; +} + +void +flatpak_transaction_set_reinstall (FlatpakTransaction *self, + gboolean reinstall) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->reinstall = reinstall; +} + +void +flatpak_transaction_set_force_uninstall (FlatpakTransaction *self, + gboolean force_uninstall) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + priv->force_uninstall = force_uninstall; +} + +static FlatpakTransactionOp * +flatpak_transaction_get_last_op_for_ref (FlatpakTransaction *self, + const char *ref) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + FlatpakTransactionOp *op; + + op = g_hash_table_lookup (priv->last_op_for_ref, ref); + + return op; +} + +static char * +subpaths_to_string (const char **subpaths) +{ + GString *s = NULL; + int i; + + if (subpaths == NULL) + return g_strdup ("[$old]"); + + if (*subpaths == 0) + return g_strdup ("[*]"); + + s = g_string_new ("["); + for (i = 0; subpaths[i] != NULL; i++) + { + if (i != 0) + g_string_append (s, ", "); + g_string_append (s, subpaths[i]); + } + g_string_append (s, "]"); + + return g_string_free (s, FALSE); +} + +static const char * +kind_to_str (FlatpakTransactionOpKind kind) +{ + switch (kind) + { + case FLATPAK_TRANSACTION_OP_KIND_INSTALL: + return "install"; + case FLATPAK_TRANSACTION_OP_KIND_UPDATE: + return "update"; + case FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE: + return "install/update"; + case FLATPAK_TRANSACTION_OP_KIND_BUNDLE: + return "install bundle"; + case FLATPAK_TRANSACTION_OP_KIND_UNINSTALL: + return "uninstall"; + } + return "unknown"; +} + +static FlatpakRemoteState * +flatpak_transaction_ensure_remote_state (FlatpakTransaction *self, + FlatpakTransactionOpKind kind, + const char *remote, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + FlatpakRemoteState *state; + + /* We don't cache local-only states, as we might later need the same state with non-local state */ + if (transaction_is_local_only (self, kind)) + return flatpak_dir_get_remote_state_local_only (priv->dir, remote, NULL, error); + + state = g_hash_table_lookup (priv->remote_states, remote); + if (state) + return state; + + state = flatpak_dir_get_remote_state_optional (priv->dir, remote, NULL, error); + + if (state) + g_hash_table_insert (priv->remote_states, state->remote_name, state); + + return state; +} + +static gboolean +kind_compatible (FlatpakTransactionOpKind a, + FlatpakTransactionOpKind b) +{ + if (a == b) + return TRUE; + + if (a == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE && + (b == FLATPAK_TRANSACTION_OP_KIND_INSTALL || + b == FLATPAK_TRANSACTION_OP_KIND_UPDATE)) + return TRUE; + + if (b == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE && + (a == FLATPAK_TRANSACTION_OP_KIND_INSTALL || + a == FLATPAK_TRANSACTION_OP_KIND_UPDATE)) + return TRUE; + + return FALSE; +} + +static FlatpakTransactionOp * +flatpak_transaction_add_op (FlatpakTransaction *self, + FlatpakTransactionOp *before_op, + const char *remote, + const char *ref, + const char **subpaths, + const char *commit, + GFile *bundle, + FlatpakTransactionOpKind kind) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + FlatpakTransactionOp *op; + g_autofree char *subpaths_str = NULL; + GList *before_l = NULL; + + subpaths_str = subpaths_to_string (subpaths); + g_debug ("Transaction: %s %s:%s%s%s%s%s%s", + kind_to_str (kind), remote, ref, + commit != NULL ? "@" : "", + commit != NULL ? commit : "", + subpaths_str, + before_op ? " before op " : "", + before_op ? before_op->ref : "" + ); + + op = flatpak_transaction_get_last_op_for_ref (self, ref); + if (op != NULL && kind_compatible (kind, op->kind)) + { + g_auto(GStrv) old_subpaths = NULL; + + old_subpaths = op->subpaths; + op->subpaths = flatpak_subpaths_merge (old_subpaths, (char **)subpaths); + + return op; + } + + op = flatpak_transaction_operation_new (remote, ref, subpaths, commit, bundle, kind); + g_hash_table_insert (priv->last_op_for_ref, g_strdup (ref), op); + + if (before_op != NULL) + before_l = g_list_find (priv->ops, before_op); + + /* Note: we build the list in reverse order, so before => after before_l == before before_l->next */ + if (before_l) + priv->ops = g_list_insert_before (priv->ops, + before_l->next, + op); + else + priv->ops = g_list_prepend (priv->ops, op); + + return op; +} + +static gboolean +add_related (FlatpakTransaction *self, + FlatpakTransactionOpKind source_kind, + FlatpakRemoteState *state, + const char *remote, + const char *ref, + FlatpakTransactionOp *source_op, + FlatpakTransactionOp *before_op, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autoptr(GPtrArray) related = NULL; + g_autoptr(GError) local_error = NULL; + int i; + + if (priv->disable_related) + return TRUE; + + if (transaction_is_local_only (self, source_kind)) + related = flatpak_dir_find_local_related (priv->dir, ref, remote, + /* Look for deployed if uninstalling, in repo otherwise */ + source_kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL, + NULL, &local_error); + else + related = flatpak_dir_find_remote_related (priv->dir, state, ref, NULL, &local_error); + + if (related == NULL) + { + g_warning (_("Warning: Problem looking for related refs: %s"), local_error->message); + g_clear_error (&local_error); + } + else if (source_kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL) + { + for (i = 0; i < related->len; i++) + { + FlatpakRelated *rel = g_ptr_array_index (related, i); + FlatpakTransactionOp *op; + + if (!rel->delete) + continue; + + op = flatpak_transaction_add_op (self, before_op, remote, rel->ref, + NULL, NULL, NULL, + FLATPAK_TRANSACTION_OP_KIND_UNINSTALL); + op->non_fatal = TRUE; + op->source_op = source_op; + } + } + else /* install or update */ + { + for (i = 0; i < related->len; i++) + { + FlatpakRelated *rel = g_ptr_array_index (related, i); + FlatpakTransactionOp *op; + + if (!rel->download) + continue; + + op = flatpak_transaction_add_op (self, before_op, remote, rel->ref, + (const char **)rel->subpaths, + NULL, NULL, + FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE); + op->non_fatal = TRUE; + op->source_op = source_op; + } + } + + return TRUE; +} + +static char * +find_runtime_remote (FlatpakTransaction *self, + const char *app_ref, + const char *runtime_ref, + FlatpakTransactionOpKind source_kind, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_auto(GStrv) remotes = NULL; + const char *app_pref; + const char *runtime_pref; + int res = -1; + + app_pref = strchr (app_ref, '/') + 1; + runtime_pref = strchr (runtime_ref, '/') + 1; + + if (transaction_is_local_only (self, source_kind)) + remotes = flatpak_dir_search_for_local_dependency (priv->dir, runtime_ref, NULL, NULL); + else + remotes = flatpak_dir_search_for_dependency (priv->dir, runtime_ref, NULL, NULL); + + if (remotes == NULL || *remotes == NULL) + { + flatpak_fail (error, _("The Application %s requires the %s which was not found"), + app_pref, runtime_pref); + return NULL; + } + + /* In the no-puil case, if only one local ref is available, assume that is the one becasue + the user chosed it interactively when pulling */ + if (priv->no_pull && g_strv_length (remotes) == 1) + res = 0; + else + g_signal_emit (self, signals[CHOOSE_REMOTE_FOR_REF], 0, app_ref, runtime_ref, remotes, &res); + + if (res >= 0 && res < g_strv_length (remotes)) + return g_strdup (remotes[res]); + + flatpak_fail (error, _("The Application %s requires the %s which is not installed"), + app_pref, runtime_pref); + return NULL; +} + + +static gboolean +add_deps (FlatpakTransaction *self, + FlatpakTransactionOpKind source_kind, + GKeyFile *metakey, + FlatpakRemoteState *state, + const char *remote, + const char *ref, + FlatpakTransactionOp **dep_op_out, + FlatpakTransactionOp **before_op_out, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autofree char *runtime_ref = NULL; + g_autofree char *full_runtime_ref = NULL; + g_autofree char *runtime_remote = NULL; + FlatpakTransactionOp *op = NULL; + + if (dep_op_out) + *dep_op_out = NULL; + if (before_op_out) + *before_op_out = NULL; + + if (!g_str_has_prefix (ref, "app/")) + return TRUE; + + if (metakey) + runtime_ref = g_key_file_get_string (metakey, "Application", "runtime", NULL); + + if (runtime_ref == NULL) + return TRUE; + + if (source_kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL) + { + g_autofree char *full_runtime_ref = g_strconcat ("runtime/", runtime_ref, NULL); + FlatpakTransactionOp *runtime_uninstall_op = flatpak_transaction_get_last_op_for_ref (self, full_runtime_ref); + + /* If the runtime this app uses is already to be uninstalled, then this uninstall must happen before + the runtime is installed */ + if (runtime_uninstall_op && + runtime_uninstall_op->kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL && + before_op_out != NULL) + { + *before_op_out = runtime_uninstall_op; + } + + return TRUE; + } + + if (priv->disable_deps) + return TRUE; + + + if (metakey) + runtime_ref = g_key_file_get_string (metakey, "Application", "runtime", NULL); + + if (runtime_ref == NULL) + return TRUE; + + full_runtime_ref = g_strconcat ("runtime/", runtime_ref, NULL); + + op = flatpak_transaction_get_last_op_for_ref (self, full_runtime_ref); + if (op == NULL) + { + g_autoptr(GError) local_error = NULL; + + if (!ref_is_installed (self, full_runtime_ref, &local_error)) + { + if (local_error != NULL) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + runtime_remote = find_runtime_remote (self, ref, full_runtime_ref, source_kind, error); + if (runtime_remote == NULL) + return FALSE; + + op = flatpak_transaction_add_op (self, NULL, runtime_remote, full_runtime_ref, NULL, NULL, NULL, + FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE); + } + else + { + /* Update if in same dir */ + if (dir_ref_is_installed (priv->dir, full_runtime_ref, &runtime_remote, NULL)) + { + g_debug ("Updating dependent runtime %s", full_runtime_ref); + op = flatpak_transaction_add_op (self, NULL, runtime_remote, full_runtime_ref, NULL, NULL, NULL, + FLATPAK_TRANSACTION_OP_KIND_UPDATE); + op->non_fatal = TRUE; + } + } + } + + if (runtime_remote != NULL && + !add_related (self, source_kind, state, runtime_remote, full_runtime_ref, op, NULL, error)) + return FALSE; + + if (dep_op_out) + *dep_op_out = op; + + return TRUE; +} + +static gboolean +flatpak_transaction_add_ref (FlatpakTransaction *self, + const char *remote, + const char *ref, + const char **subpaths, + const char *commit, + FlatpakTransactionOpKind kind, + GFile *bundle, + const char *metadata, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autofree char *origin = NULL; + const char *pref; + g_autoptr(GKeyFile) metakey = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree char *origin_remote = NULL; + FlatpakRemoteState *state = NULL; + FlatpakTransactionOp *dep_op = NULL; + FlatpakTransactionOp *before_op = NULL; + FlatpakTransactionOp *main_op; + g_autoptr(GVariant) commit_metadata = NULL; + + if (remote_name_is_file (remote)) + { + g_auto(GStrv) parts = NULL; + parts = g_strsplit (ref, "/", -1); + + origin_remote = flatpak_dir_create_origin_remote (priv->dir, + remote, /* uri */ + parts[1], + "Local repo", + ref, + NULL, + NULL, + NULL, error); + if (origin_remote == NULL) + return FALSE; + + g_ptr_array_add (priv->added_origin_remotes, g_strdup (origin_remote)); + + remote = origin_remote; + } + + pref = strchr (ref, '/') + 1; + + /* install or update */ + if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE) + { + if (!dir_ref_is_installed (priv->dir, ref, &origin, NULL)) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + _("%s not installed"), pref); + return FALSE; + } + + if (flatpak_dir_get_remote_disabled (priv->dir, origin)) + { + g_debug (_("Remote %s disabled, ignoring %s update"), origin, pref); + return TRUE; + } + remote = origin; + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL) + { + if (!priv->reinstall && + dir_ref_is_installed (priv->dir, ref, &origin, NULL)) + { + if (g_strcmp0 (remote, origin) == 0) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED, + _("%s is already installed"), pref); + return FALSE; + } + else + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_DIFFERENT_REMOTE, + _("%s is already installed from remote %s"), pref, origin); + return FALSE; + } + } + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL) + { + if (!dir_ref_is_installed (priv->dir, ref, &origin, NULL)) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED, + _("%s not installed"), pref); + return FALSE; + } + + remote = origin; + } + + /* This should have been passed int or found out above */ + g_assert (remote != NULL); + + state = flatpak_transaction_ensure_remote_state (self, kind, remote, error); + if (state == NULL) + return FALSE; + + if (metadata == NULL) + { + /* Should we use local state */ + if (transaction_is_local_only (self, kind)) + { + g_autoptr(GVariant) commit_data = flatpak_dir_read_latest_commit (priv->dir, remote, ref, + NULL, NULL); + if (commit_data) + { + commit_metadata = g_variant_get_child_value (commit_data, 0); + g_variant_lookup (commit_metadata, "xa.metadata", "&s", &metadata); + if (metadata == NULL) + g_debug ("No xa.metadata in local commit"); + } + } + else if (!flatpak_remote_state_lookup_cache (state, ref, NULL, NULL, &metadata, &local_error)) + { + g_warning (_("Warning: Can't find dependencies: %s"), local_error->message); + g_clear_error (&local_error); + } + } + + if (metadata) + { + metakey = g_key_file_new (); + if (!g_key_file_load_from_data (metakey, metadata, -1, 0, NULL)) + g_clear_object (&metakey); + } + + if (metakey && kind != FLATPAK_TRANSACTION_OP_KIND_UNINSTALL && + !flatpak_check_required_version (ref, metakey, error)) + return FALSE; + + if (!add_deps (self, kind, metakey, state, remote, ref, &dep_op, &before_op, error)) + return FALSE; + + main_op = flatpak_transaction_add_op (self, before_op, remote, ref, subpaths, commit, bundle, kind); + main_op->source_op = dep_op; + + if (!add_related (self, kind, state, remote, ref, main_op, before_op, error)) + return FALSE; + + return TRUE; +} + +gboolean +flatpak_transaction_add_install (FlatpakTransaction *self, + const char *remote, + const char *ref, + const char **subpaths, + GError **error) +{ + const char *all_paths[] = { NULL }; + + /* If we install with no special args pull all subpaths */ + if (subpaths == NULL) + subpaths = all_paths; + + return flatpak_transaction_add_ref (self, remote, ref, subpaths, NULL, FLATPAK_TRANSACTION_OP_KIND_INSTALL, NULL, NULL, error); +} + +gboolean +flatpak_transaction_add_install_bundle (FlatpakTransaction *self, + GFile *file, + GBytes *gpg_data, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autofree char *remote = NULL; + g_autofree char *ref = NULL; + g_autofree char *metadata = NULL; + gboolean created_remote; + + remote = flatpak_dir_ensure_bundle_remote (priv->dir, file, gpg_data, + &ref, &metadata, &created_remote, + NULL, error); + if (remote == NULL) + return FALSE; + + if (!flatpak_dir_recreate_repo (priv->dir, NULL, error)) + return FALSE; + + return flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, FLATPAK_TRANSACTION_OP_KIND_BUNDLE, file, metadata, error); +} + +gboolean +flatpak_transaction_add_update (FlatpakTransaction *self, + const char *ref, + const char **subpaths, + const char *commit, + GError **error) +{ + const char *all_paths[] = { NULL }; + + /* If specify an empty subpath, that means all subpaths */ + if (subpaths != NULL && subpaths[0] != NULL && subpaths[0][0] == 0) + subpaths = all_paths; + + return flatpak_transaction_add_ref (self, NULL, ref, subpaths, commit, FLATPAK_TRANSACTION_OP_KIND_UPDATE, NULL, NULL, error); +} + +gboolean +flatpak_transaction_add_uninstall (FlatpakTransaction *self, + const char *ref, + GError **error) +{ + return flatpak_transaction_add_ref (self, NULL, ref, NULL, NULL, FLATPAK_TRANSACTION_OP_KIND_UNINSTALL, NULL, NULL, error); +} + +static gboolean +flatpak_transaction_update_metadata (FlatpakTransaction *self, + GCancellable *cancellable, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_auto(GStrv) remotes = NULL; + int i; + GList *l; + g_autoptr(GHashTable) ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + /* Collect all dir+remotes used in this transaction */ + + for (l = priv->ops; l != NULL; l = l->next) + { + FlatpakTransactionOp *op = l->data; + g_hash_table_add (ht, g_strdup (op->remote)); + } + remotes = (char **)g_hash_table_get_keys_as_array (ht, NULL); + g_hash_table_steal_all (ht); /* Move ownership to remotes */ + + /* Update metadata for said remotes */ + for (i = 0; remotes[i] != NULL; i++) + { + char *remote = remotes[i]; + g_autoptr(GError) my_error = NULL; + + g_debug ("Updating remote metadata for %s", remote); + if (!flatpak_dir_update_remote_configuration (priv->dir, remote, cancellable, &my_error)) + g_warning (_("Error updating remote metadata for '%s': %s"), remote, my_error->message); + } + + /* Reload changed configuration */ + if (!flatpak_dir_recreate_repo (priv->dir, cancellable, error)) + return FALSE; + + return TRUE; +} + +static void +emit_new_op (FlatpakTransaction *self, FlatpakTransactionOp *op, FlatpakTransactionProgress *progress) +{ + g_signal_emit (self, signals[NEW_OPERATION], 0, op->ref, op->remote, + op->bundle ? flatpak_file_get_path_cached (op->bundle) : NULL, + op_type_from_resolved_kind (op->kind), progress); +} + +static void +emit_op_done (FlatpakTransaction *self, + FlatpakTransactionOp *op, + FlatpakTransactionResult details) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autofree char *commit = NULL; + + if (priv->no_deploy) + commit = flatpak_dir_read_latest (priv->dir, op->remote, op->ref, NULL, NULL, NULL); + else + { + g_autoptr(GVariant) deploy_data = flatpak_dir_get_deploy_data (priv->dir, op->ref, NULL, NULL); + if (deploy_data) + commit = g_strdup (flatpak_deploy_data_get_commit (deploy_data)); + } + + g_signal_emit (self, signals[OPERATION_DONE], 0, op->ref, op->remote, + op_type_from_resolved_kind (op->kind), + commit, details); +} + +gboolean +flatpak_transaction_run (FlatpakTransaction *self, + GCancellable *cancellable, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + GList *l; + gboolean succeeded = TRUE; + gboolean needs_prune = FALSE; + gboolean needs_triggers = FALSE; + g_autoptr(GMainContextPopDefault) main_context = NULL; + int i; + + if (!priv->no_pull && + !flatpak_transaction_update_metadata (self, cancellable, error)) + return FALSE; + + /* Work around ostree-pull spinning the default main context for the sync calls */ + main_context = flatpak_main_context_new_default (); + + priv->ops = g_list_reverse (priv->ops); + + for (l = priv->ops; l != NULL; l = l->next) + { + FlatpakTransactionOp *op = l->data; + g_autoptr(GError) local_error = NULL; + gboolean res = TRUE; + const char *pref; + FlatpakTransactionOpKind kind; + FlatpakRemoteState *state; + + kind = op->kind; + if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE) + { + g_autoptr(GVariant) deploy_data = NULL; + + if (dir_ref_is_installed (priv->dir, op->ref, NULL, &deploy_data)) + { + /* Don't use the remote from related ref on update, always use + the current remote. */ + g_free (op->remote); + op->remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data)); + + kind = FLATPAK_TRANSACTION_OP_KIND_UPDATE; + } + else + kind = FLATPAK_TRANSACTION_OP_KIND_INSTALL; + + op->kind = kind; + } + + pref = strchr (op->ref, '/') + 1; + + if (op->source_op && (op->source_op->failed) && + /* Allow installing an app if the runtime failed to update (i.e. is installed) because + * the app should still run, and otherwise you could never install the app until the runtime + * remote is fixed. */ + !(op->source_op->kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE && g_str_has_prefix (op->ref, "app/"))) + { + g_set_error (&local_error, FLATPAK_ERROR, FLATPAK_ERROR_SKIPPED, + _("Skipping %s due to previous error"), pref); + res = FALSE; + } + else if ((state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, &local_error)) == NULL) + { + res = FALSE; + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL) + { + g_autoptr(FlatpakTransactionProgress) progress = flatpak_transaction_progress_new (); + + emit_new_op (self, op, progress); + + res = flatpak_dir_install (priv->dir , + priv->no_pull, + priv->no_deploy, + priv->disable_static_deltas, + priv->reinstall, + state, op->ref, + (const char **)op->subpaths, + progress->ostree_progress, + cancellable, &local_error); + flatpak_transaction_progress_done (progress); + + if (res) + { + emit_op_done (self, op, 0); + + /* Normally we don't need to prune after install, because it makes no old objects + stale. However if we reinstall, that is not true. */ + if (!priv->no_pull && priv->reinstall) + needs_prune = TRUE; + + if (g_str_has_prefix (op->ref, "app")) + needs_triggers = TRUE; + } + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE) + { + g_auto(OstreeRepoFinderResultv) check_results = NULL; + + g_autofree char *target_commit = flatpak_dir_check_for_update (priv->dir, state, op->ref, op->commit, + (const char **)op->subpaths, + priv->no_pull, + &check_results, + cancellable, &local_error); + if (target_commit != NULL) + { + g_autoptr(FlatpakTransactionProgress) progress = flatpak_transaction_progress_new (); + FlatpakTransactionResult result_details = 0; + + emit_new_op (self, op, progress); + + res = flatpak_dir_update (priv->dir, + priv->no_pull, + priv->no_deploy, + priv->disable_static_deltas, + op->commit != NULL, /* Allow downgrade if we specify commit */ + state, op->ref, target_commit, + (const OstreeRepoFinderResult * const *) check_results, + (const char **)op->subpaths, + progress->ostree_progress, + cancellable, &local_error); + flatpak_transaction_progress_done (progress); + + /* Handle noop-updates */ + if (!res && g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) + { + res = TRUE; + g_clear_error (&local_error); + + result_details |= FLATPAK_TRANSACTION_RESULT_NO_CHANGE; + } + + if (res) + { + emit_op_done (self, op, result_details); + + if (!priv->no_pull) + needs_prune = TRUE; + + if (g_str_has_prefix (op->ref, "app")) + needs_triggers = TRUE; + } + } + else + { + res = FALSE; + if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) + { + res = TRUE; + g_clear_error (&local_error); + } + } + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_BUNDLE) + { + g_autoptr(FlatpakTransactionProgress) progress = flatpak_transaction_progress_new (); + emit_new_op (self, op, progress); + res = flatpak_dir_install_bundle (priv->dir, op->bundle, + op->remote, NULL, + cancellable, &local_error); + flatpak_transaction_progress_done (progress); + + if (res) + { + emit_op_done (self, op, 0); + needs_prune = TRUE; + needs_triggers = TRUE; + } + } + else if (kind == FLATPAK_TRANSACTION_OP_KIND_UNINSTALL) + { + g_autoptr(FlatpakTransactionProgress) progress = flatpak_transaction_progress_new (); + FlatpakHelperUninstallFlags flags = 0; + + if (priv->disable_prune) + flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF; + + if (priv->force_uninstall) + flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE; + + emit_new_op (self, op, progress); + + res = flatpak_dir_uninstall (priv->dir, op->ref, flags, + cancellable, &local_error); + + flatpak_transaction_progress_done (progress); + + if (res) + { + emit_op_done (self, op, 0); + needs_prune = TRUE; + + if (g_str_has_prefix (op->ref, "app")) + needs_triggers = TRUE; + } + } + else + g_assert_not_reached (); + + if (res) + { + g_autoptr(GVariant) deploy_data = NULL; + deploy_data = flatpak_dir_get_deploy_data (priv->dir, op->ref, NULL, NULL); + + if (deploy_data) + { + const char *eol = flatpak_deploy_data_get_eol (deploy_data); + const char *eol_rebase = flatpak_deploy_data_get_eol_rebase (deploy_data); + + if (eol || eol_rebase) + g_signal_emit (self, signals[END_OF_LIFED], 0, + op->ref, eol, eol_rebase); + } + } + + if (!res) + { + gboolean do_cont = FALSE; + FlatpakTransactionErrorDetails error_details = 0; + + op->failed = TRUE; + + if (op->non_fatal) + error_details |= FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL; + + g_signal_emit (self, signals[OPERATION_ERROR], 0, + op->ref, + op->remote, + op_type_from_resolved_kind (kind), + local_error, error_details, + &do_cont); + + if (!do_cont) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED, + _("Aborted due to failure")); + succeeded = FALSE; + break; + } + } + } + + if (needs_triggers) + flatpak_dir_run_triggers (priv->dir, cancellable, NULL); + + if (needs_prune && !priv->disable_prune) + flatpak_dir_prune (priv->dir, cancellable, NULL); + + for (i = 0; i < priv->added_origin_remotes->len; i++) + flatpak_dir_prune_origin_remote (priv->dir, g_ptr_array_index (priv->added_origin_remotes, i)); + + return succeeded; +} diff -Nru flatpak-0.11.7/common/flatpak-transaction.h flatpak-0.11.8.3/common/flatpak-transaction.h --- flatpak-0.11.7/common/flatpak-transaction.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-transaction.h 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,175 @@ +/* + * Copyright © 2016 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined(__FLATPAK_H_INSIDE__) && !defined(FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_TRANSACTION_H__ +#define __FLATPAK_TRANSACTION_H__ + +#include +#include + +#define FLATPAK_TYPE_TRANSACTION flatpak_transaction_get_type () +#define FLATPAK_TYPE_TRANSACTION_PROGRESS flatpak_transaction_progress_get_type () + +/** + * FlatpakTransactionOperationType + * @FLATPAK_TRANSACTION_OPERATION_INSTALL: Install a ref from a remote + * @FLATPAK_TRANSACTION_OPERATION_UPDATE: Update an installed ref + * @FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: Install a bundle from a file + * @FLATPAK_TRANSACTION_OPERATION_UNINSTALL: Uninstall a ref + * + * The type of a transaction, used in FlatpakTransaction::new-operation + */ +typedef enum { + FLATPAK_TRANSACTION_OPERATION_INSTALL, + FLATPAK_TRANSACTION_OPERATION_UPDATE, + FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, + FLATPAK_TRANSACTION_OPERATION_UNINSTALL +} FlatpakTransactionOperationType; + +/** + * FlatpakTransactionErrorDetails + * @FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL: The operation failure was not fatal + * + * The details for FlatpakTransaction::operation-error + */ +typedef enum { + FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL = 1 << 0, +} FlatpakTransactionErrorDetails; + +/** + * FlatpakTransactionResult + * @FLATPAK_TRANSACTION_RESULT_NO_CHANGE: The update caused no changes + */ +typedef enum { + FLATPAK_TRANSACTION_RESULT_NO_CHANGE = 1 << 0, +} FlatpakTransactionResult; + +FLATPAK_EXTERN +G_DECLARE_FINAL_TYPE (FlatpakTransactionProgress, flatpak_transaction_progress, FLATPAK, TRANSACTION_PROGRESS, GObject) + +FLATPAK_EXTERN +G_DECLARE_DERIVABLE_TYPE (FlatpakTransaction, flatpak_transaction, FLATPAK, TRANSACTION, GObject) + +struct _FlatpakTransactionClass +{ + GObjectClass parent_class; + + void (*new_operation) (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + const char *bundle_path, + FlatpakTransactionOperationType operation_type, + FlatpakTransactionProgress *progress); + void (*operation_done) (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + FlatpakTransactionOperationType operation_type, + const char *commit, + FlatpakTransactionResult details); + gboolean (*operation_error) (FlatpakTransaction *transaction, + const char *ref, + const char *remote, + FlatpakTransactionOperationType operation_type, + GError *error, + FlatpakTransactionErrorDetails detail); + int (*choose_remote_for_ref) (FlatpakTransaction *transaction, + const char *for_ref, + const char *runtime_ref, + const char * const *remotes); + void (*end_of_lifed) (FlatpakTransaction *transaction, + const char *ref, + const char *reason, + const char *rebase); + + gpointer padding[12]; +}; + +FLATPAK_EXTERN +FlatpakTransaction *flatpak_transaction_new_for_installation (FlatpakInstallation *installation, + GCancellable *cancellable, + GError **error); + +FLATPAK_EXTERN +void flatpak_transaction_progress_set_update_frequency (FlatpakTransactionProgress *self, + guint update_frequency); +FLATPAK_EXTERN +char * flatpak_transaction_progress_get_status (FlatpakTransactionProgress *self); +FLATPAK_EXTERN +gboolean flatpak_transaction_progress_get_is_estimating (FlatpakTransactionProgress *self); +FLATPAK_EXTERN +int flatpak_transaction_progress_get_progress (FlatpakTransactionProgress *self); + +FLATPAK_EXTERN +void flatpak_transaction_set_no_pull (FlatpakTransaction *self, + gboolean no_pull); +FLATPAK_EXTERN +void flatpak_transaction_set_no_deploy (FlatpakTransaction *self, + gboolean no_deploy); +FLATPAK_EXTERN +void flatpak_transaction_set_disable_static_deltas (FlatpakTransaction *self, + gboolean disable_static_deltas); +FLATPAK_EXTERN +void flatpak_transaction_set_disable_prune (FlatpakTransaction *self, + gboolean disable_prune); +FLATPAK_EXTERN +void flatpak_transaction_set_disable_dependencies (FlatpakTransaction *self, + gboolean disable_dependencies); +FLATPAK_EXTERN +void flatpak_transaction_set_disable_related (FlatpakTransaction *self, + gboolean disable_related); +FLATPAK_EXTERN +void flatpak_transaction_set_reinstall (FlatpakTransaction *self, + gboolean reinstall); +FLATPAK_EXTERN +void flatpak_transaction_set_force_uninstall (FlatpakTransaction *self, + gboolean force_uninstall); +FLATPAK_EXTERN +gboolean flatpak_transaction_run (FlatpakTransaction *self, + GCancellable *cancellable, + GError **error); +FLATPAK_EXTERN +gboolean flatpak_transaction_add_install (FlatpakTransaction *self, + const char *remote, + const char *ref, + const char **subpaths, + GError **error); +FLATPAK_EXTERN +gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction *self, + GFile *file, + GBytes *gpg_data, + GError **error); +FLATPAK_EXTERN +gboolean flatpak_transaction_add_update (FlatpakTransaction *self, + const char *ref, + const char **subpaths, + const char *commit, + GError **error); +FLATPAK_EXTERN +gboolean flatpak_transaction_add_uninstall (FlatpakTransaction *self, + const char *ref, + GError **error); +FLATPAK_EXTERN +gboolean flatpak_transaction_is_empty (FlatpakTransaction *self); + +#endif /* __FLATPAK_TRANSACTION_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-transaction-private.h flatpak-0.11.8.3/common/flatpak-transaction-private.h --- flatpak-0.11.7/common/flatpak-transaction-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-transaction-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,28 @@ +/* + * 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_TRANSACTION_PRIVATE_H__ +#define __FLATPAK_TRANSACTION_PRIVATE_H__ + +#include "flatpak-transaction.h" + +#include "flatpak-dir-private.h" + +#endif /* __FLATPAK_TRANSACTION_PRIVATE_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-utils.c flatpak-0.11.8.3/common/flatpak-utils.c --- flatpak-0.11.7/common/flatpak-utils.c 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-utils.c 2018-06-11 14:52:37.000000000 +0100 @@ -20,11 +20,12 @@ #include "config.h" -#include "flatpak-utils.h" -#include "lib/flatpak-error.h" -#include "flatpak-dir.h" -#include "flatpak-oci-registry.h" -#include "flatpak-run.h" +#include "flatpak-utils-private.h" +#include "flatpak-error.h" +#include "flatpak-dir-private.h" +#include "flatpak-oci-registry-private.h" +#include "flatpak-run-private.h" +#include "valgrind-private.h" #include @@ -631,7 +632,8 @@ (c >= '0' && c <= '9'); } -/** flatpak_is_valid_name: +/** + * flatpak_is_valid_name: * @string: The string to check * @error: Return location for an error * @@ -1746,7 +1748,7 @@ if (!g_ascii_isalnum (c) && !(c == '-' || c == '/' || c == '~' || c == ':' || c == '.' || c == '_' || - c == '=')) + c == '=' || c == '@')) return TRUE; arg++; } @@ -1754,12 +1756,16 @@ } char * -flatpak_quote_argv (const char *argv[]) +flatpak_quote_argv (const char *argv[], + gssize len) { GString *res = g_string_new (""); int i; - for (i = 0; argv[i] != NULL; i++) + if (len == -1) + len = g_strv_length ((char **)argv); + + for (i = 0; i < len; i++) { if (i != 0) g_string_append_c (res, ' '); @@ -2186,7 +2192,9 @@ return glnx_throw_errno_prefix (error, "lseek"); if (memfd != -1) { - if (fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0) + /* Valgrind doesn't currently handle G_ADD_SEALS, so lets not seal when debugging... */ + if ((!RUNNING_ON_VALGRIND) && + fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0) return glnx_throw_errno_prefix (error, "fcntl(F_ADD_SEALS)"); /* The other values can stay default */ tmpf->fd = glnx_steal_fd (&memfd); @@ -2576,10 +2584,10 @@ #ifdef FLATPAK_ENABLE_P2P g_autoptr(GKeyFile) config = NULL; - config = ostree_repo_copy_config (repo); if (!ostree_repo_set_collection_id (repo, collection_id, error)) return FALSE; + config = ostree_repo_copy_config (repo); if (!ostree_repo_write_config (repo, config, error)) return FALSE; #endif /* FLATPAK_ENABLE_P2P */ @@ -2706,7 +2714,7 @@ base_input = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (base_input)); if (!G_IS_UNIX_INPUT_STREAM (base_input)) - return flatpak_fail (error, "Unable to find size of commit %s, not an unix stream\n", checksum); + return flatpak_fail (error, "Unable to find size of commit %s, not an unix stream", checksum); fd = g_unix_input_stream_get_fd (G_UNIX_INPUT_STREAM (base_input)); @@ -3594,8 +3602,8 @@ g_clear_error (&my_error); } - /* We updated icons for our component, so we're done */ - break; + /* We might match other prefixes, so keep on going */ + component = component->next_sibling; } } @@ -4933,13 +4941,13 @@ metadata_builder); if (manifest_ref == NULL) { - flatpak_fail (error, "No ref specified for OCI image %s\n", digest); + flatpak_fail (error, "No ref specified for OCI image %s", digest); return NULL; } if (strcmp (manifest_ref, ref) != 0) { - flatpak_fail (error, "Wrong ref (%s) specified for OCI image %s, expected %s\n", manifest_ref, digest, ref); + flatpak_fail (error, "Wrong ref (%s) specified for OCI image %s, expected %s", manifest_ref, digest, ref); return NULL; } @@ -5008,7 +5016,7 @@ if (!g_str_has_prefix (layer->digest, "sha256:") || strcmp (layer->digest + strlen ("sha256:"), layer_checksum) != 0) { - flatpak_fail (error, "Wrong layer checksum, expected %s, was %s\n", layer->digest, layer_checksum); + flatpak_fail (error, "Wrong layer checksum, expected %s, was %s", layer->digest, layer_checksum); goto error; } @@ -5560,496 +5568,6 @@ return TRUE; } -/* Uncomment to get debug traces in /tmp/flatpak-completion-debug.txt (nice - * to not have it interfere with stdout/stderr) - */ -#if 0 -void -flatpak_completion_debug (const gchar *format, ...) -{ - va_list var_args; - gchar *s; - static FILE *f = NULL; - - va_start (var_args, format); - s = g_strdup_vprintf (format, var_args); - if (f == NULL) - f = fopen ("/tmp/flatpak-completion-debug.txt", "a+"); - fprintf (f, "%s\n", s); - fflush (f); - g_free (s); -} -#else -void -flatpak_completion_debug (const gchar *format, ...) -{ -} -#endif - -static gboolean -is_word_separator (char c) -{ - return g_ascii_isspace (c); -} - -void -flatpak_complete_file (FlatpakCompletion *completion, - const char *file_type) -{ - flatpak_completion_debug ("completing FILE"); - g_print ("%s\n", file_type); -} - -void -flatpak_complete_dir (FlatpakCompletion *completion) -{ - flatpak_completion_debug ("completing DIR"); - g_print ("%s\n", "__FLATPAK_DIR"); -} - -void -flatpak_complete_word (FlatpakCompletion *completion, - char *format, ...) -{ - va_list args; - const char *rest; - const char *shell_cur; - const char *shell_cur_end; - g_autofree char *string = NULL; - - g_return_if_fail (format != NULL); - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" - va_start (args, format); - string = g_strdup_vprintf (format, args); - va_end (args); -#pragma GCC diagnostic pop - - if (!g_str_has_prefix (string, completion->cur)) - return; - - shell_cur = completion->shell_cur ? completion->shell_cur : ""; - - rest = string + strlen (completion->cur); - - shell_cur_end = shell_cur + strlen(shell_cur); - while (shell_cur_end > shell_cur && - rest > string && - shell_cur_end[-1] == rest[-1] && - /* I'm not sure exactly what bash is doing here with =, but this seems to work... */ - shell_cur_end[-1] != '=') - { - rest--; - shell_cur_end--; - } - - flatpak_completion_debug ("completing word: '%s' (%s)", string, rest); - - g_print ("%s\n", rest); -} - -void -flatpak_complete_ref (FlatpakCompletion *completion, - OstreeRepo *repo) -{ - g_autoptr(GHashTable) refs = NULL; - flatpak_completion_debug ("completing REF"); - - if (ostree_repo_list_refs (repo, - NULL, - &refs, NULL, NULL)) - { - GHashTableIter hashiter; - gpointer hashkey, hashvalue; - - g_hash_table_iter_init (&hashiter, refs); - while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))) - { - const char *ref = (const char *)hashkey; - if (!(g_str_has_prefix (ref, "runtime/") || - g_str_has_prefix (ref, "app/"))) - continue; - flatpak_complete_word (completion, "%s", ref); - } - } -} - -static int -find_current_element (const char *str) -{ - int count = 0; - - if (g_str_has_prefix (str, "app/")) - str += strlen ("app/"); - else if (g_str_has_prefix (str, "runtime/")) - str += strlen ("runtime/"); - - while (str != NULL && count <= 3) - { - str = strchr (str, '/'); - count++; - if (str != NULL) - str = str + 1; - } - - return count; -} - -void -flatpak_complete_partial_ref (FlatpakCompletion *completion, - FlatpakKinds kinds, - const char *only_arch, - FlatpakDir *dir, - const char *remote) -{ - FlatpakKinds matched_kinds; - const char *pref; - g_autofree char *id = NULL; - g_autofree char *arch = NULL; - g_autofree char *branch = NULL; - g_auto(GStrv) refs = NULL; - int element; - const char *cur_parts[4] = { NULL }; - g_autoptr(GError) error = NULL; - int i; - - pref = completion->cur; - element = find_current_element (pref); - - flatpak_split_partial_ref_arg_novalidate (pref, kinds, - NULL, NULL, - &matched_kinds, &id, &arch, &branch); - - cur_parts[1] = id; - cur_parts[2] = arch ? arch : ""; - cur_parts[3] = branch ? branch : ""; - - if (remote) - { - refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], - (element > 1) ? id : NULL, - (element > 3) ? branch : NULL, - (element > 2 )? arch : only_arch, - matched_kinds, NULL, &error); - } - else - { - refs = flatpak_dir_find_installed_refs (dir, - (element > 1) ? id : NULL, - (element > 3) ? branch : NULL, - (element > 2 )? arch : only_arch, - matched_kinds, &error); - } - if (refs == NULL) - flatpak_completion_debug ("find refs error: %s", error->message); - for (i = 0; refs != NULL && refs[i] != NULL; i++) - { - int j; - g_autoptr(GString) comp = NULL; - g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL); - if (parts == NULL) - continue; - - if (!g_str_has_prefix (parts[element], cur_parts[element])) - continue; - - if (flatpak_id_has_subref_suffix (parts[element])) - { - char *last_dot = strrchr (parts[element], '.'); - - if (last_dot == NULL) - continue; /* Shouldn't really happen */ - - /* Only complete to subrefs is fully matching real part. - * For example, only match org.foo.Bar.Sources for - * "org.foo.Bar", "org.foo.Bar." or "org.foo.Bar.S", but - * not for "org.foo" or other shorter prefixes. - */ - if (strncmp (parts[element], cur_parts[element], last_dot - parts[element] - 1) != 0) - continue; - } - - comp = g_string_new (pref); - g_string_append (comp, parts[element] + strlen (cur_parts[element])); - - /* Only complete on the last part if the user explicitly adds a / */ - if (element >= 2) - { - for (j = element + 1; j < 4; j++) - { - g_string_append (comp, "/"); - g_string_append (comp, parts[j]); - } - } - - flatpak_complete_word (completion, "%s", comp->str); - } -} - -static gboolean -switch_already_in_line (FlatpakCompletion *completion, - GOptionEntry *entry) -{ - guint i = 0; - guint line_part_len = 0; - - for (; i < completion->original_argc; ++i) - { - line_part_len = strlen (completion->original_argv[i]); - if (line_part_len > 2 && - g_strcmp0 (&completion->original_argv[i][2], entry->long_name) == 0) - return TRUE; - - if (line_part_len == 2 && - completion->original_argv[i][1] == entry->short_name) - return TRUE; - } - - return FALSE; -} - -static gboolean -should_filter_out_option_from_completion (FlatpakCompletion *completion, - GOptionEntry *entry) -{ - switch (entry->arg) - { - case G_OPTION_ARG_NONE: - case G_OPTION_ARG_STRING: - case G_OPTION_ARG_INT: - case G_OPTION_ARG_FILENAME: - case G_OPTION_ARG_DOUBLE: - case G_OPTION_ARG_INT64: - return switch_already_in_line (completion, entry); - default: - return FALSE; - } -} - -void -flatpak_complete_options (FlatpakCompletion *completion, - GOptionEntry *entries) -{ - GOptionEntry *e = entries; - int i; - - while (e->long_name != NULL) - { - if (e->arg_description) - { - g_autofree char *prefix = g_strdup_printf ("--%s=", e->long_name); - - if (g_str_has_prefix (completion->cur, prefix)) - { - if (strcmp (e->arg_description, "ARCH") == 0) - { - const char *arches[] = {"i386", "x86_64", "aarch64", "arm"}; - for (i = 0; i < G_N_ELEMENTS (arches); i++) - flatpak_complete_word (completion, "%s%s ", prefix, arches[i]); - } - else if (strcmp (e->arg_description, "SHARE") == 0) - { - for (i = 0; flatpak_context_shares[i] != NULL; i++) - flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_shares[i]); - } - else if (strcmp (e->arg_description, "DEVICE") == 0) - { - for (i = 0; flatpak_context_devices[i] != NULL; i++) - flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_devices[i]); - } - else if (strcmp (e->arg_description, "FEATURE") == 0) - { - for (i = 0; flatpak_context_features[i] != NULL; i++) - flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_features[i]); - } - else if (strcmp (e->arg_description, "SOCKET") == 0) - { - for (i = 0; flatpak_context_sockets[i] != NULL; i++) - flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_sockets[i]); - } - else if (strcmp (e->arg_description, "FILE") == 0) - { - flatpak_complete_file (completion, "__FLATPAK_FILE"); - } - else - flatpak_complete_word (completion, "%s", prefix); - } - else - flatpak_complete_word (completion, "%s", prefix); - } - else - { - /* If this is just a switch, then don't add it multiple - * times */ - if (!should_filter_out_option_from_completion (completion, e)) { - flatpak_complete_word (completion, "--%s ", e->long_name); - } else { - flatpak_completion_debug ("switch --%s is already in line %s", e->long_name, completion->line); - } - } - - /* We may end up checking switch_already_in_line twice, but this is - * for simplicity's sake - the alternative solution would be to - * continue the loop early and have to increment e. */ - if (e->short_name != 0) - { - /* This is a switch, we may not want to add it */ - if (!e->arg_description) - { - if (!should_filter_out_option_from_completion (completion, e)) { - flatpak_complete_word (completion, "-%c ", e->short_name); - } else { - flatpak_completion_debug ("switch -%c is already in line %s", e->short_name, completion->line); - } - } - else - { - flatpak_complete_word (completion, "-%c ", e->short_name); - } - } - e++; - } -} - -static gchar * -pick_word_at (const char *s, - int cursor, - int *out_word_begins_at) -{ - int begin, end; - - if (s[0] == '\0') - { - if (out_word_begins_at != NULL) - *out_word_begins_at = -1; - return NULL; - } - - if (is_word_separator (s[cursor]) && ((cursor > 0 && is_word_separator(s[cursor-1])) || cursor == 0)) - { - if (out_word_begins_at != NULL) - *out_word_begins_at = cursor; - return g_strdup (""); - } - - while (!is_word_separator (s[cursor - 1]) && cursor > 0) - cursor--; - begin = cursor; - - end = begin; - while (!is_word_separator (s[end]) && s[end] != '\0') - end++; - - if (out_word_begins_at != NULL) - *out_word_begins_at = begin; - - return g_strndup (s + begin, end - begin); -} - -static gboolean -parse_completion_line_to_argv (const char *initial_completion_line, - FlatpakCompletion *completion) -{ - gboolean parse_result = g_shell_parse_argv (initial_completion_line, - &completion->original_argc, - &completion->original_argv, - NULL); - - /* Make a shallow copy of argv, which will be our "working set" */ - completion->argc = completion->original_argc; - completion->argv = g_memdup (completion->original_argv, - sizeof (gchar *) * (completion->original_argc + 1)); - - return parse_result; -} - -FlatpakCompletion * -flatpak_completion_new (const char *arg_line, - const char *arg_point, - const char *arg_cur) -{ - FlatpakCompletion *completion; - g_autofree char *initial_completion_line = NULL; - int _point; - char *endp; - int cur_begin; - int i; - - _point = strtol (arg_point, &endp, 10); - if (endp == arg_point || *endp != '\0') - return NULL; - - completion = g_new0 (FlatpakCompletion, 1); - completion->line = g_strdup (arg_line); - completion->shell_cur = g_strdup (arg_cur); - completion->point = _point; - - flatpak_completion_debug ("========================================"); - flatpak_completion_debug ("completion_point=%d", completion->point); - flatpak_completion_debug ("completion_shell_cur='%s'", completion->shell_cur); - flatpak_completion_debug ("----"); - flatpak_completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789"); - flatpak_completion_debug ("'%s'", completion->line); - flatpak_completion_debug (" %*s^", completion->point, ""); - - /* compute cur and prev */ - completion->prev = NULL; - completion->cur = pick_word_at (completion->line, completion->point, &cur_begin); - if (cur_begin > 0) - { - gint prev_end; - for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--) - { - if (!is_word_separator (completion->line[prev_end])) - { - completion->prev = pick_word_at (completion->line, prev_end, NULL); - break; - } - } - - initial_completion_line = g_strndup (completion->line, cur_begin); - } - else - initial_completion_line = g_strdup (""); - - flatpak_completion_debug ("'%s'", initial_completion_line); - flatpak_completion_debug ("----"); - - flatpak_completion_debug (" cur='%s'", completion->cur); - flatpak_completion_debug ("prev='%s'", completion->prev); - - if (!parse_completion_line_to_argv (initial_completion_line, - completion)) - { - /* it's very possible the command line can't be parsed (for - * example, missing quotes etc) - in that case, we just - * don't autocomplete at all - */ - flatpak_completion_free (completion); - return NULL; - } - - flatpak_completion_debug ("completion_argv %i:", completion->original_argc); - for (i = 0; i < completion->original_argc; i++) - flatpak_completion_debug (completion->original_argv[i]); - - flatpak_completion_debug ("----"); - - return completion; -} - -void -flatpak_completion_free (FlatpakCompletion *completion) -{ - g_free (completion->cur); - g_free (completion->prev); - g_free (completion->line); - g_free (completion->argv); - g_strfreev (completion->original_argv); - g_free (completion); -} - /* In this NULL means don't care about these paths, while an empty array means match anything */ char ** @@ -6146,66 +5664,6 @@ return (char **)g_ptr_array_free (langs, FALSE); } -#define BAR_LENGTH 20 -#define BAR_CHARS " -=#" - -void -flatpak_terminal_progress_cb (const char *status, - guint progress, - gboolean estimating, - gpointer user_data) -{ - g_autoptr(GString) str = g_string_new (""); - FlatpakTerminalProgress *term = user_data; - int i; - int n_full, remainder, partial; - int width, padded_width; - - if (!term->inited) - { - struct winsize w; - term->n_columns = 80; - if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w) == 0) - term->n_columns = w.ws_col; - term->last_width = 0; - term->inited = 1; - } - - g_string_append (str, "["); - - n_full = (BAR_LENGTH * progress) / 100; - remainder = progress - (n_full * 100 / BAR_LENGTH); - partial = (remainder * strlen(BAR_CHARS) * BAR_LENGTH) / 100; - - for (i = 0; i < n_full; i++) - g_string_append_c (str, BAR_CHARS[strlen(BAR_CHARS)-1]); - - if (i < BAR_LENGTH) - { - g_string_append_c (str, BAR_CHARS[partial]); - i++; - } - - for (; i < BAR_LENGTH; i++) - g_string_append (str, " "); - - g_string_append (str, "] "); - g_string_append (str, status); - - g_print ("\r"); - width = MIN (strlen (str->str), term->n_columns); - padded_width = MAX (term->last_width, width); - term->last_width = width; - g_print ("%-*.*s", padded_width, padded_width, str->str); -} - -void -flatpak_terminal_progress_end (FlatpakTerminalProgress *term) -{ - if (term->inited) - g_print("\n"); -} - static inline guint get_write_progress (guint outstanding_writes) { @@ -6436,9 +5894,6 @@ g_object_set_data (G_OBJECT (ostree_progress), "callback", progress); g_object_set_data (G_OBJECT (ostree_progress), "last_progress", GUINT_TO_POINTER (0)); - if (progress == flatpak_terminal_progress_cb) - g_object_set_data (G_OBJECT (ostree_progress), "update-frequency", GUINT_TO_POINTER (FLATPAK_CLI_UPDATE_FREQUENCY)); - return ostree_progress; } @@ -6458,3 +5913,37 @@ g_debug ("Opening %s flatpak installation at path %s", dir_name, dir_path_str); } } + +gboolean +flatpak_check_required_version (const char *ref, + GKeyFile *metakey, + GError **error) +{ + g_autofree char *required_version = NULL; + const char *group; + int required_major, required_minor, required_micro; + + if (g_str_has_prefix (ref, "app/")) + group = "Application"; + else + group = "Runtime"; + + required_version = g_key_file_get_string (metakey, group, "required-flatpak", NULL); + if (required_version) + { + if (sscanf (required_version, "%d.%d.%d", &required_major, &required_minor, &required_micro) != 3) + g_warning ("Invalid require-flatpak argument %s", required_version); + else + { + if (required_major > PACKAGE_MAJOR_VERSION || + (required_major == PACKAGE_MAJOR_VERSION && required_minor > PACKAGE_MINOR_VERSION) || + (required_major == PACKAGE_MAJOR_VERSION && required_minor == PACKAGE_MINOR_VERSION && required_micro > PACKAGE_MICRO_VERSION)) + { + g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NEED_NEW_FLATPAK, _("%s needs a later flatpak version (%s)"), ref, required_version); + return FALSE; + } + } + } + + return TRUE; +} diff -Nru flatpak-0.11.7/common/flatpak-utils.h flatpak-0.11.8.3/common/flatpak-utils.h --- flatpak-0.11.7/common/flatpak-utils.h 2018-05-02 13:58:21.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-utils.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,719 +0,0 @@ -/* - * Copyright © 2014 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 . - * - * Authors: - * Alexander Larsson - */ - -#ifndef __FLATPAK_UTILS_H__ -#define __FLATPAK_UTILS_H__ - -#include - -#include "libglnx/libglnx.h" -#include -#include -#include -#include -#include "flatpak-dbus.h" -#include "flatpak-document-dbus.h" -#include "flatpak-context.h" -#include -#include - -typedef enum { - FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV = 1 << 0, -} FlatpakHostCommandFlags; - -typedef void (*FlatpakLoadUriProgress) (guint64 downloaded_bytes, - gpointer user_data); - - -#define FLATPAK_ANSI_BOLD_ON "\x1b[1m" -#define FLATPAK_ANSI_BOLD_OFF "\x1b[22m" -#define FLATPAK_ANSI_RED "\x1b[31m" -#define FLATPAK_ANSI_COLOR_RESET "\x1b[0m" - -/* https://bugzilla.gnome.org/show_bug.cgi?id=766370 */ -#if !GLIB_CHECK_VERSION(2, 49, 3) -#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{0,}} -#define FLATPAK_VARIANT_DICT_INITIALIZER {{0,}} -#else -#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{{0,}}} -#define FLATPAK_VARIANT_DICT_INITIALIZER {{{0,}}} -#endif - -/* https://github.com/GNOME/libglnx/pull/38 - * Note by using #define rather than wrapping via a static inline, we - * don't have to re-define attributes like G_GNUC_PRINTF. - */ -#define flatpak_fail glnx_throw - -void flatpak_debug2 (const char *format, ...) G_GNUC_PRINTF(1, 2); - -gint flatpak_strcmp0_ptr (gconstpointer a, - gconstpointer b); - -gboolean flatpak_has_path_prefix (const char *str, - const char *prefix); - -const char * flatpak_path_match_prefix (const char *pattern, - const char *path); - -gboolean flatpak_fancy_output (void); - -const char * flatpak_get_arch (void); -const char ** flatpak_get_arches (void); -gboolean flatpak_is_linux32_arch (const char *arch); - -const char ** flatpak_get_gl_drivers (void); -gboolean flatpak_extension_matches_reason (const char *extension_id, - const char *reason, - gboolean default_value); - -const char * flatpak_get_bwrap (void); - -char **flatpak_subpaths_merge (char **subpaths1, - char **subpaths2); - -char *flatpak_get_lang_from_locale (const char *locale); -char **flatpak_get_current_locale_langs (void); - -void flatpak_migrate_from_xdg_app (void); - -GFile *flatpak_file_new_tmp_in (GFile *dir, - const char *templatename, - GError **error); - -gboolean flatpak_write_update_checksum (GOutputStream *out, - gconstpointer data, - gsize len, - gsize *out_bytes_written, - GChecksum *checksum, - GCancellable *cancellable, - GError **error); - - -gboolean flatpak_splice_update_checksum (GOutputStream *out, - GInputStream *in, - GChecksum *checksum, - FlatpakLoadUriProgress progress, - gpointer progress_data, - GCancellable *cancellable, - GError **error); - -GBytes * flatpak_read_stream (GInputStream *in, - gboolean null_terminate, - GError **error); - -gboolean flatpak_variant_save (GFile *dest, - GVariant *variant, - GCancellable *cancellable, - GError **error); -GVariant * flatpak_gvariant_new_empty_string_dict (void); -void flatpak_variant_builder_init_from_variant (GVariantBuilder *builder, - const char *type, - GVariant *variant); -gboolean flatpak_variant_bsearch_str (GVariant *array, - const char *str, - int *out_pos); -GVariant *flatpak_repo_load_summary (OstreeRepo *repo, - GError **error); -char ** flatpak_summary_match_subrefs (GVariant *summary, - const char *collection_id, - const char *ref); -gboolean flatpak_summary_lookup_ref (GVariant *summary, - const char *collection_id, - const char *ref, - char **out_checksum, - GVariant **out_variant); - -gboolean flatpak_name_matches_one_wildcard_prefix (const char *string, - const char * const *maybe_wildcard_prefixes, - gboolean require_exact_match); - -gboolean flatpak_get_allowed_exports (const char *source_path, - const char *app_id, - FlatpakContext *context, - char ***allowed_extensions_out, - char ***allowed_prefixes_out, - gboolean *require_exact_match_out); - -gboolean flatpak_is_valid_name (const char *string, - GError **error); -gboolean flatpak_is_valid_branch (const char *string, - GError **error); - -char * flatpak_make_valid_id_prefix (const char *orig_id); -gboolean flatpak_id_has_subref_suffix (const char *id); - -char **flatpak_decompose_ref (const char *ref, - GError **error); - -FlatpakKinds flatpak_kinds_from_bools (gboolean app, gboolean runtime); - -gboolean flatpak_split_partial_ref_arg (const char *partial_ref, - FlatpakKinds default_kinds, - const char *default_arch, - const char *default_branch, - FlatpakKinds *out_kinds, - char **out_id, - char **out_arch, - char **out_branch, - GError **error); -gboolean flatpak_split_partial_ref_arg_novalidate (const char *partial_ref, - FlatpakKinds default_kinds, - const char *default_arch, - const char *default_branch, - FlatpakKinds *out_kinds, - char **out_id, - char **out_arch, - char **out_branch); - -char * flatpak_compose_ref (gboolean app, - const char *name, - const char *branch, - const char *arch, - GError **error); - -char * flatpak_build_untyped_ref (const char *runtime, - const char *branch, - const char *arch); -char * flatpak_build_runtime_ref (const char *runtime, - const char *branch, - const char *arch); -char * flatpak_build_app_ref (const char *app, - const char *branch, - const char *arch); -char * flatpak_find_current_ref (const char *app_id, - GCancellable *cancellable, - GError **error); -GFile *flatpak_find_deploy_dir_for_ref (const char *ref, - FlatpakDir **dir_out, - GCancellable *cancellable, - GError **error); -GFile * flatpak_find_files_dir_for_ref (const char *ref, - GCancellable *cancellable, - GError **error); -GFile * flatpak_find_unmaintained_extension_dir_if_exists (const char *name, - const char *arch, - const char *branch, - GCancellable *cancellable); -FlatpakDeploy * flatpak_find_deploy_for_ref (const char *ref, - const char *commit, - GCancellable *cancellable, - GError **error); -char ** flatpak_list_deployed_refs (const char *type, - const char *name_prefix, - const char *branch, - const char *arch, - GCancellable *cancellable, - GError **error); -char ** flatpak_list_unmaintained_refs (const char *name_prefix, - const char *branch, - const char *arch, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_remove_dangling_symlinks (GFile *dir, - GCancellable *cancellable, - GError **error); - -#if !GLIB_CHECK_VERSION (2, 40, 0) -static inline gboolean -g_key_file_save_to_file (GKeyFile *key_file, - const gchar *filename, - GError **error) -{ - gchar *contents; - gboolean success; - gsize length; - - contents = g_key_file_to_data (key_file, &length, NULL); - success = g_file_set_contents (filename, contents, length, error); - g_free (contents); - - return success; -} -#endif - -gboolean flatpak_g_ptr_array_contains_string (GPtrArray *array, const char *str); - -/* Returns the first string in subset that is not in strv */ -static inline const gchar * -g_strv_subset (const gchar * const *strv, - const gchar * const *subset) -{ - int i; - - for (i = 0; subset[i]; i++) - { - const char *key; - - key = subset[i]; - if (!g_strv_contains (strv, key)) - return key; - } - - return NULL; -} - -static inline void -flatpak_auto_unlock_helper (GMutex **mutex) -{ - if (*mutex) - g_mutex_unlock (*mutex); -} - -static inline GMutex * -flatpak_auto_lock_helper (GMutex *mutex) -{ - if (mutex) - g_mutex_lock (mutex); - return mutex; -} - -gboolean -flatpak_switch_symlink_and_remove (const char *symlink_path, - const char *target, - GError **error); -gint flatpak_mkstempat (int dir_fd, - gchar *tmpl, - int flags, - int mode); - -gboolean flatpak_repo_set_title (OstreeRepo *repo, - const char *title, - GError **error); -gboolean flatpak_repo_set_redirect_url (OstreeRepo *repo, - const char *redirect_url, - GError **error); -gboolean flatpak_repo_set_default_branch (OstreeRepo *repo, - const char *branch, - GError **error); -gboolean flatpak_repo_set_collection_id (OstreeRepo *repo, - const char *collection_id, - GError **error); -gboolean flatpak_repo_set_deploy_collection_id (OstreeRepo *repo, - gboolean deploy_collection_id, - GError **error); -gboolean flatpak_repo_set_gpg_keys (OstreeRepo *repo, - GBytes *bytes, - GError **error); -gboolean flatpak_repo_update (OstreeRepo *repo, - const char **gpg_key_ids, - const char *gpg_homedir, - GCancellable *cancellable, - GError **error); -gboolean flatpak_repo_collect_sizes (OstreeRepo *repo, - GFile *root, - guint64 *installed_size, - guint64 *download_size, - GCancellable *cancellable, - GError **error); -GVariant *flatpak_commit_get_extra_data_sources (GVariant *commitv, - GError **error); -GVariant *flatpak_repo_get_extra_data_sources (OstreeRepo *repo, - const char *rev, - GCancellable *cancellable, - GError **error); -void flatpak_repo_parse_extra_data_sources (GVariant *extra_data_sources, - int index, - const char **name, - guint64 *download_size, - guint64 *installed_size, - const guchar **sha256, - const char **uri); -gboolean flatpak_mtree_create_root (OstreeRepo *repo, - OstreeMutableTree *mtree, - GCancellable *cancellable, - GError **error); - -GVariant * flatpak_bundle_load (GFile *file, - char **commit, - char **ref, - char **origin, - char **runtime_repo, - char **app_metadata, - guint64 *installed_size, - GBytes **gpg_keys, - char **collection_id, - GError **error); - -gboolean flatpak_pull_from_bundle (OstreeRepo *repo, - GFile *file, - const char *remote, - const char *ref, - gboolean require_gpg_signature, - GCancellable *cancellable, - GError **error); - -typedef void (*FlatpakOciPullProgress) (guint64 total_size, guint64 pulled_size, - guint32 n_layers, guint32 pulled_layers, - gpointer data); - -char * flatpak_pull_from_oci (OstreeRepo *repo, - FlatpakOciRegistry *registry, - const char *oci_repository, - const char *digest, - FlatpakOciManifest *manifest, - const char *remote, - const char *ref, - FlatpakOciPullProgress progress_cb, - gpointer progress_data, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry, - FlatpakOciRegistry *registry, - const char *oci_repository, - const char *digest, - FlatpakOciPullProgress progress_cb, - gpointer progress_data, - GCancellable *cancellable, - GError **error); - -typedef struct -{ - char *id; - char *installed_id; - char *commit; - char *ref; - char *directory; - char *files_path; - char *subdir_suffix; - char *add_ld_path; - char **merge_dirs; - int priority; - gboolean needs_tmpfs; - gboolean is_unmaintained; -} FlatpakExtension; - -void flatpak_extension_free (FlatpakExtension *extension); - -void flatpak_parse_extension_with_tag (const char *extension, - char **name, - char **tag); - -GList *flatpak_list_extensions (GKeyFile *metakey, - const char *arch, - const char *branch); - -char * flatpak_quote_argv (const char *argv[]); -gboolean flatpak_file_arg_has_suffix (const char *arg, const char *suffix); - -const char *flatpak_file_get_path_cached (GFile *file); - -GFile *flatpak_build_file_va (GFile *base, - va_list args); -GFile *flatpak_build_file (GFile *base, ...) G_GNUC_NULL_TERMINATED; - -gboolean flatpak_openat_noatime (int dfd, - const char *name, - int *ret_fd, - GCancellable *cancellable, - GError **error); - -typedef enum { - FLATPAK_CP_FLAGS_NONE = 0, - FLATPAK_CP_FLAGS_MERGE = 1<<0, - FLATPAK_CP_FLAGS_NO_CHOWN = 1<<1, - FLATPAK_CP_FLAGS_MOVE = 1<<2, -} FlatpakCpFlags; - -gboolean flatpak_cp_a (GFile *src, - GFile *dest, - FlatpakCpFlags flags, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_zero_mtime (int parent_dfd, - const char *rel_path, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_mkdir_p (GFile *dir, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_rm_rf (GFile *dir, - GCancellable *cancellable, - GError **error); - -char * flatpak_readlink (const char *path, - GError **error); -char * flatpak_resolve_link (const char *path, - GError **error); -char * flatpak_canonicalize_filename (const char *path); - -gboolean flatpak_file_rename (GFile *from, - GFile *to, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_open_in_tmpdir_at (int tmpdir_fd, - int mode, - char *tmpl, - GOutputStream **out_stream, - GCancellable *cancellable, - GError **error); - -gboolean -flatpak_buffer_to_sealed_memfd_or_tmpfile (GLnxTmpfile *tmpf, - const char *name, - const char *str, - size_t len, - GError **error); - -static inline void -flatpak_temp_dir_destroy (void *p) -{ - GFile *dir = p; - - if (dir) - { - flatpak_rm_rf (dir, NULL, NULL); - g_object_unref (dir); - } -} - -typedef GFile FlatpakTempDir; -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTempDir, flatpak_temp_dir_destroy) - - -typedef OstreeRepo FlatpakRepoTransaction; - -static inline void -flatpak_repo_transaction_cleanup (void *p) -{ - OstreeRepo *repo = p; - - if (repo) - { - g_autoptr(GError) error = NULL; - if (!ostree_repo_abort_transaction (repo, NULL, &error)) - g_warning ("Error aborting ostree transaction: %s", error->message); - } -} - -static inline FlatpakRepoTransaction * -flatpak_repo_transaction_start (OstreeRepo *repo, - GCancellable *cancellable, - GError **error) -{ - if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) - return NULL; - return (FlatpakRepoTransaction *)repo; -} -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRepoTransaction, flatpak_repo_transaction_cleanup) - -#define AUTOLOCK(name) G_GNUC_UNUSED __attribute__((cleanup (flatpak_auto_unlock_helper))) GMutex * G_PASTE (auto_unlock, __LINE__) = flatpak_auto_lock_helper (&G_LOCK_NAME (name)) - -/* OSTREE_CHECK_VERSION was added immediately after the 2017.3 release */ -#ifndef OSTREE_CHECK_VERSION -#define OSTREE_CHECK_VERSION(year, minor) (0) -#endif -/* Cleanups are always exported in 2017.4, and some git releases between 2017.3 and 2017.4. - We actually check against 2017.3 so that we work on the git releases *after* 2017.3 - which is safe, because the real OSTREE_CHECK_VERSION macro was added after 2017.3 - too. */ -#if !OSTREE_CHECK_VERSION(2017, 3) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoCommitModifier, ostree_repo_commit_modifier_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoDevInoCache, ostree_repo_devino_cache_unref) -#endif - -#ifndef SOUP_AUTOCLEANUPS_H -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupSession, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupMessage, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupRequest, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupRequestHTTP, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupURI, soup_uri_free) -#endif - -#if !JSON_CHECK_VERSION(1,1,2) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonArray, json_array_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonBuilder, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonGenerator, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonNode, json_node_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonObject, json_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonParser, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonPath, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonReader, g_object_unref) -#endif - -#if !GLIB_CHECK_VERSION(2, 43, 4) -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUnixFDList, g_object_unref) -#endif - -/* This uses a weird Auto prefix to avoid conflicts with later added autogenerated autoptr support, per: - * https://git.gnome.org/browse/glib/commit/?id=1c6cd5f0a3104aa9b62c7f1d3086181f63e71b59 - */ -typedef FlatpakSessionHelper AutoFlatpakSessionHelper; -G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoFlatpakSessionHelper, g_object_unref) - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (XdpDbusDocuments, g_object_unref) - -typedef struct FlatpakXml FlatpakXml; - -struct FlatpakXml -{ - gchar *element_name; /* NULL == text */ - char **attribute_names; - char **attribute_values; - char *text; - FlatpakXml *parent; - FlatpakXml *first_child; - FlatpakXml *last_child; - FlatpakXml *next_sibling; -}; - -FlatpakXml *flatpak_xml_new (const gchar *element_name); -FlatpakXml *flatpak_xml_new_text (const gchar *text); -void flatpak_xml_add (FlatpakXml *parent, - FlatpakXml *node); -void flatpak_xml_free (FlatpakXml *node); -FlatpakXml *flatpak_xml_parse (GInputStream *in, - gboolean compressed, - GCancellable *cancellable, - GError **error); -void flatpak_xml_to_string (FlatpakXml *node, - GString *res); -FlatpakXml *flatpak_xml_unlink (FlatpakXml *node, - FlatpakXml *prev_sibling); -FlatpakXml *flatpak_xml_find (FlatpakXml *node, - const char *type, - FlatpakXml **prev_child_out); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakXml, flatpak_xml_free); - - -FlatpakXml *flatpak_appstream_xml_new (void); -gboolean flatpak_appstream_xml_migrate (FlatpakXml *source, - FlatpakXml *dest, - const char *ref, - const char *id, - GKeyFile *metadata); -gboolean flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root, - GBytes **uncompressed, - GBytes **compressed, - GError **error); -gboolean flatpak_repo_generate_appstream (OstreeRepo *repo, - const char **gpg_key_ids, - const char *gpg_homedir, - guint64 timestamp, - GCancellable *cancellable, - GError **error); - -gboolean flatpak_allocate_tmpdir (int tmpdir_dfd, - const char *tmpdir_relpath, - const char *tmpdir_prefix, - char **tmpdir_name_out, - int *tmpdir_fd_out, - GLnxLockFile *file_lock_out, - gboolean *reusing_dir_out, - GCancellable *cancellable, - GError **error); - - -gboolean flatpak_yes_no_prompt (const char *prompt, ...) G_GNUC_PRINTF(1, 2); -long flatpak_number_prompt (int min, int max, const char *prompt, ...) G_GNUC_PRINTF(3, 4); - -SoupSession * flatpak_create_soup_session (const char *user_agent); - -typedef enum { - FLATPAK_HTTP_FLAGS_NONE = 0, - FLATPAK_HTTP_FLAGS_ACCEPT_OCI = 1<<0, -} FlatpakHTTPFlags; - -GBytes * flatpak_load_http_uri (SoupSession *soup_session, - const char *uri, - FlatpakHTTPFlags flags, - const char *etag, - char **out_etag, - FlatpakLoadUriProgress progress, - gpointer user_data, - GCancellable *cancellable, - GError **error); -gboolean flatpak_download_http_uri (SoupSession *soup_session, - const char *uri, - FlatpakHTTPFlags flags, - GOutputStream *out, - FlatpakLoadUriProgress progress, - gpointer user_data, - GCancellable *cancellable, - GError **error); - -struct FlatpakCompletion { - char *shell_cur; - char *cur; - char *prev; - char *line; - int point; - char **argv; - char **original_argv; - int argc; - int original_argc; -}; - -void flatpak_completion_debug (const gchar *format, ...); - -FlatpakCompletion *flatpak_completion_new (const char *arg_line, - const char *arg_point, - const char *arg_cur); -void flatpak_complete_word (FlatpakCompletion *completion, - char *format, - ...) G_GNUC_PRINTF(2,3); -void flatpak_complete_ref (FlatpakCompletion *completion, - OstreeRepo *repo); -void flatpak_complete_partial_ref (FlatpakCompletion *completion, - FlatpakKinds kinds, - const char *only_arch, - FlatpakDir *dir, - const char *remote); -void flatpak_complete_file (FlatpakCompletion *completion, - const char *file_type); -void flatpak_complete_dir (FlatpakCompletion *completion); -void flatpak_complete_options (FlatpakCompletion *completion, - GOptionEntry *entries); -void flatpak_completion_free (FlatpakCompletion *completion); - -typedef struct { - int inited; - int n_columns; - int last_width; -} FlatpakTerminalProgress; - -void flatpak_terminal_progress_cb (const char *status, - guint progress, - gboolean estimating, - gpointer user_data); -void flatpak_terminal_progress_end (FlatpakTerminalProgress *term); - -typedef void (*FlatpakProgressCallback)(const char *status, - guint progress, - gboolean estimating, - gpointer user_data); - -OstreeAsyncProgress *flatpak_progress_new (FlatpakProgressCallback progress, - gpointer progress_data); - -void flatpak_log_dir_access (FlatpakDir *dir); - -#endif /* __FLATPAK_UTILS_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-utils-private.h flatpak-0.11.8.3/common/flatpak-utils-private.h --- flatpak-0.11.7/common/flatpak-utils-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-utils-private.h 2018-06-11 14:52:37.000000000 +0100 @@ -0,0 +1,698 @@ +/* + * Copyright © 2014 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 . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_UTILS_H__ +#define __FLATPAK_UTILS_H__ + +#include + +#include "libglnx/libglnx.h" +#include +#include +#include +#include +#include "flatpak-dbus-generated.h" +#include "flatpak-document-dbus-generated.h" +#include "flatpak-context-private.h" +#include +#include + +#define AUTOFS_SUPER_MAGIC 0x0187 + +typedef enum { + FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV = 1 << 0, +} FlatpakHostCommandFlags; + +typedef void (*FlatpakLoadUriProgress) (guint64 downloaded_bytes, + gpointer user_data); + + +#define FLATPAK_ANSI_BOLD_ON "\x1b[1m" +#define FLATPAK_ANSI_BOLD_OFF "\x1b[22m" +#define FLATPAK_ANSI_RED "\x1b[31m" +#define FLATPAK_ANSI_COLOR_RESET "\x1b[0m" + +/* https://bugzilla.gnome.org/show_bug.cgi?id=766370 */ +#if !GLIB_CHECK_VERSION(2, 49, 3) +#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{0,}} +#define FLATPAK_VARIANT_DICT_INITIALIZER {{0,}} +#else +#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{{0,}}} +#define FLATPAK_VARIANT_DICT_INITIALIZER {{{0,}}} +#endif + +/* https://github.com/GNOME/libglnx/pull/38 + * Note by using #define rather than wrapping via a static inline, we + * don't have to re-define attributes like G_GNUC_PRINTF. + */ +#define flatpak_fail glnx_throw + +void flatpak_debug2 (const char *format, ...) G_GNUC_PRINTF(1, 2); + +gint flatpak_strcmp0_ptr (gconstpointer a, + gconstpointer b); + +gboolean flatpak_has_path_prefix (const char *str, + const char *prefix); + +const char * flatpak_path_match_prefix (const char *pattern, + const char *path); + +gboolean flatpak_fancy_output (void); + +const char * flatpak_get_arch (void); +const char ** flatpak_get_arches (void); +gboolean flatpak_is_linux32_arch (const char *arch); + +const char ** flatpak_get_gl_drivers (void); +gboolean flatpak_extension_matches_reason (const char *extension_id, + const char *reason, + gboolean default_value); + +const char * flatpak_get_bwrap (void); + +char **flatpak_subpaths_merge (char **subpaths1, + char **subpaths2); + +char *flatpak_get_lang_from_locale (const char *locale); +char **flatpak_get_current_locale_langs (void); + +void flatpak_migrate_from_xdg_app (void); + +GFile *flatpak_file_new_tmp_in (GFile *dir, + const char *templatename, + GError **error); + +gboolean flatpak_write_update_checksum (GOutputStream *out, + gconstpointer data, + gsize len, + gsize *out_bytes_written, + GChecksum *checksum, + GCancellable *cancellable, + GError **error); + + +gboolean flatpak_splice_update_checksum (GOutputStream *out, + GInputStream *in, + GChecksum *checksum, + FlatpakLoadUriProgress progress, + gpointer progress_data, + GCancellable *cancellable, + GError **error); + +GBytes * flatpak_read_stream (GInputStream *in, + gboolean null_terminate, + GError **error); + +gboolean flatpak_variant_save (GFile *dest, + GVariant *variant, + GCancellable *cancellable, + GError **error); +GVariant * flatpak_gvariant_new_empty_string_dict (void); +void flatpak_variant_builder_init_from_variant (GVariantBuilder *builder, + const char *type, + GVariant *variant); +gboolean flatpak_variant_bsearch_str (GVariant *array, + const char *str, + int *out_pos); +GVariant *flatpak_repo_load_summary (OstreeRepo *repo, + GError **error); +char ** flatpak_summary_match_subrefs (GVariant *summary, + const char *collection_id, + const char *ref); +gboolean flatpak_summary_lookup_ref (GVariant *summary, + const char *collection_id, + const char *ref, + char **out_checksum, + GVariant **out_variant); + +gboolean flatpak_name_matches_one_wildcard_prefix (const char *string, + const char * const *maybe_wildcard_prefixes, + gboolean require_exact_match); + +gboolean flatpak_get_allowed_exports (const char *source_path, + const char *app_id, + FlatpakContext *context, + char ***allowed_extensions_out, + char ***allowed_prefixes_out, + gboolean *require_exact_match_out); + +gboolean flatpak_is_valid_name (const char *string, + GError **error); +gboolean flatpak_is_valid_branch (const char *string, + GError **error); + +char * flatpak_make_valid_id_prefix (const char *orig_id); +gboolean flatpak_id_has_subref_suffix (const char *id); + +char **flatpak_decompose_ref (const char *ref, + GError **error); + +FlatpakKinds flatpak_kinds_from_bools (gboolean app, gboolean runtime); + +gboolean flatpak_split_partial_ref_arg (const char *partial_ref, + FlatpakKinds default_kinds, + const char *default_arch, + const char *default_branch, + FlatpakKinds *out_kinds, + char **out_id, + char **out_arch, + char **out_branch, + GError **error); +gboolean flatpak_split_partial_ref_arg_novalidate (const char *partial_ref, + FlatpakKinds default_kinds, + const char *default_arch, + const char *default_branch, + FlatpakKinds *out_kinds, + char **out_id, + char **out_arch, + char **out_branch); + +char * flatpak_compose_ref (gboolean app, + const char *name, + const char *branch, + const char *arch, + GError **error); + +char * flatpak_build_untyped_ref (const char *runtime, + const char *branch, + const char *arch); +char * flatpak_build_runtime_ref (const char *runtime, + const char *branch, + const char *arch); +char * flatpak_build_app_ref (const char *app, + const char *branch, + const char *arch); +char * flatpak_find_current_ref (const char *app_id, + GCancellable *cancellable, + GError **error); +GFile *flatpak_find_deploy_dir_for_ref (const char *ref, + FlatpakDir **dir_out, + GCancellable *cancellable, + GError **error); +GFile * flatpak_find_files_dir_for_ref (const char *ref, + GCancellable *cancellable, + GError **error); +GFile * flatpak_find_unmaintained_extension_dir_if_exists (const char *name, + const char *arch, + const char *branch, + GCancellable *cancellable); +FlatpakDeploy * flatpak_find_deploy_for_ref (const char *ref, + const char *commit, + GCancellable *cancellable, + GError **error); +char ** flatpak_list_deployed_refs (const char *type, + const char *name_prefix, + const char *branch, + const char *arch, + GCancellable *cancellable, + GError **error); +char ** flatpak_list_unmaintained_refs (const char *name_prefix, + const char *branch, + const char *arch, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_remove_dangling_symlinks (GFile *dir, + GCancellable *cancellable, + GError **error); + +#if !GLIB_CHECK_VERSION (2, 40, 0) +static inline gboolean +g_key_file_save_to_file (GKeyFile *key_file, + const gchar *filename, + GError **error) +{ + gchar *contents; + gboolean success; + gsize length; + + contents = g_key_file_to_data (key_file, &length, NULL); + success = g_file_set_contents (filename, contents, length, error); + g_free (contents); + + return success; +} +#endif + +gboolean flatpak_g_ptr_array_contains_string (GPtrArray *array, const char *str); + +/* Returns the first string in subset that is not in strv */ +static inline const gchar * +g_strv_subset (const gchar * const *strv, + const gchar * const *subset) +{ + int i; + + for (i = 0; subset[i]; i++) + { + const char *key; + + key = subset[i]; + if (!g_strv_contains (strv, key)) + return key; + } + + return NULL; +} + +static inline void +flatpak_auto_unlock_helper (GMutex **mutex) +{ + if (*mutex) + g_mutex_unlock (*mutex); +} + +static inline GMutex * +flatpak_auto_lock_helper (GMutex *mutex) +{ + if (mutex) + g_mutex_lock (mutex); + return mutex; +} + +gboolean +flatpak_switch_symlink_and_remove (const char *symlink_path, + const char *target, + GError **error); +gint flatpak_mkstempat (int dir_fd, + gchar *tmpl, + int flags, + int mode); + +gboolean flatpak_repo_set_title (OstreeRepo *repo, + const char *title, + GError **error); +gboolean flatpak_repo_set_redirect_url (OstreeRepo *repo, + const char *redirect_url, + GError **error); +gboolean flatpak_repo_set_default_branch (OstreeRepo *repo, + const char *branch, + GError **error); +gboolean flatpak_repo_set_collection_id (OstreeRepo *repo, + const char *collection_id, + GError **error); +gboolean flatpak_repo_set_deploy_collection_id (OstreeRepo *repo, + gboolean deploy_collection_id, + GError **error); +gboolean flatpak_repo_set_gpg_keys (OstreeRepo *repo, + GBytes *bytes, + GError **error); +gboolean flatpak_repo_update (OstreeRepo *repo, + const char **gpg_key_ids, + const char *gpg_homedir, + GCancellable *cancellable, + GError **error); +gboolean flatpak_repo_collect_sizes (OstreeRepo *repo, + GFile *root, + guint64 *installed_size, + guint64 *download_size, + GCancellable *cancellable, + GError **error); +GVariant *flatpak_commit_get_extra_data_sources (GVariant *commitv, + GError **error); +GVariant *flatpak_repo_get_extra_data_sources (OstreeRepo *repo, + const char *rev, + GCancellable *cancellable, + GError **error); +void flatpak_repo_parse_extra_data_sources (GVariant *extra_data_sources, + int index, + const char **name, + guint64 *download_size, + guint64 *installed_size, + const guchar **sha256, + const char **uri); +gboolean flatpak_mtree_create_root (OstreeRepo *repo, + OstreeMutableTree *mtree, + GCancellable *cancellable, + GError **error); + +GVariant * flatpak_bundle_load (GFile *file, + char **commit, + char **ref, + char **origin, + char **runtime_repo, + char **app_metadata, + guint64 *installed_size, + GBytes **gpg_keys, + char **collection_id, + GError **error); + +gboolean flatpak_pull_from_bundle (OstreeRepo *repo, + GFile *file, + const char *remote, + const char *ref, + gboolean require_gpg_signature, + GCancellable *cancellable, + GError **error); + +typedef void (*FlatpakOciPullProgress) (guint64 total_size, guint64 pulled_size, + guint32 n_layers, guint32 pulled_layers, + gpointer data); + +char * flatpak_pull_from_oci (OstreeRepo *repo, + FlatpakOciRegistry *registry, + const char *oci_repository, + const char *digest, + FlatpakOciManifest *manifest, + const char *remote, + const char *ref, + FlatpakOciPullProgress progress_cb, + gpointer progress_data, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry, + FlatpakOciRegistry *registry, + const char *oci_repository, + const char *digest, + FlatpakOciPullProgress progress_cb, + gpointer progress_data, + GCancellable *cancellable, + GError **error); + +typedef struct +{ + char *id; + char *installed_id; + char *commit; + char *ref; + char *directory; + char *files_path; + char *subdir_suffix; + char *add_ld_path; + char **merge_dirs; + int priority; + gboolean needs_tmpfs; + gboolean is_unmaintained; +} FlatpakExtension; + +void flatpak_extension_free (FlatpakExtension *extension); + +void flatpak_parse_extension_with_tag (const char *extension, + char **name, + char **tag); + +GList *flatpak_list_extensions (GKeyFile *metakey, + const char *arch, + const char *branch); + +char * flatpak_quote_argv (const char *argv[], + gssize len); +gboolean flatpak_file_arg_has_suffix (const char *arg, const char *suffix); + +const char *flatpak_file_get_path_cached (GFile *file); + +GFile *flatpak_build_file_va (GFile *base, + va_list args); +GFile *flatpak_build_file (GFile *base, ...) G_GNUC_NULL_TERMINATED; + +gboolean flatpak_openat_noatime (int dfd, + const char *name, + int *ret_fd, + GCancellable *cancellable, + GError **error); + +typedef enum { + FLATPAK_CP_FLAGS_NONE = 0, + FLATPAK_CP_FLAGS_MERGE = 1<<0, + FLATPAK_CP_FLAGS_NO_CHOWN = 1<<1, + FLATPAK_CP_FLAGS_MOVE = 1<<2, +} FlatpakCpFlags; + +gboolean flatpak_cp_a (GFile *src, + GFile *dest, + FlatpakCpFlags flags, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_zero_mtime (int parent_dfd, + const char *rel_path, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_mkdir_p (GFile *dir, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_rm_rf (GFile *dir, + GCancellable *cancellable, + GError **error); + +char * flatpak_readlink (const char *path, + GError **error); +char * flatpak_resolve_link (const char *path, + GError **error); +char * flatpak_canonicalize_filename (const char *path); + +gboolean flatpak_file_rename (GFile *from, + GFile *to, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_open_in_tmpdir_at (int tmpdir_fd, + int mode, + char *tmpl, + GOutputStream **out_stream, + GCancellable *cancellable, + GError **error); + +gboolean +flatpak_buffer_to_sealed_memfd_or_tmpfile (GLnxTmpfile *tmpf, + const char *name, + const char *str, + size_t len, + GError **error); + +static inline void +flatpak_temp_dir_destroy (void *p) +{ + GFile *dir = p; + + if (dir) + { + flatpak_rm_rf (dir, NULL, NULL); + g_object_unref (dir); + } +} + +typedef GFile FlatpakTempDir; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTempDir, flatpak_temp_dir_destroy) + +typedef GMainContext GMainContextPopDefault; +static inline void +flatpak_main_context_pop_default_destroy (void *p) +{ + GMainContext *main_context = p; + + if (main_context) + g_main_context_pop_thread_default (main_context); +} + +static inline GMainContextPopDefault * +flatpak_main_context_new_default (void) +{ + GMainContext *main_context = g_main_context_new (); + g_main_context_push_thread_default (main_context); + return main_context; +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GMainContextPopDefault, flatpak_main_context_pop_default_destroy) + +typedef OstreeRepo FlatpakRepoTransaction; + +static inline void +flatpak_repo_transaction_cleanup (void *p) +{ + OstreeRepo *repo = p; + + if (repo) + { + g_autoptr(GError) error = NULL; + if (!ostree_repo_abort_transaction (repo, NULL, &error)) + g_warning ("Error aborting ostree transaction: %s", error->message); + } +} + +static inline FlatpakRepoTransaction * +flatpak_repo_transaction_start (OstreeRepo *repo, + GCancellable *cancellable, + GError **error) +{ + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return NULL; + return (FlatpakRepoTransaction *)repo; +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRepoTransaction, flatpak_repo_transaction_cleanup) + +#define AUTOLOCK(name) G_GNUC_UNUSED __attribute__((cleanup (flatpak_auto_unlock_helper))) GMutex * G_PASTE (auto_unlock, __LINE__) = flatpak_auto_lock_helper (&G_LOCK_NAME (name)) + +/* OSTREE_CHECK_VERSION was added immediately after the 2017.3 release */ +#ifndef OSTREE_CHECK_VERSION +#define OSTREE_CHECK_VERSION(year, minor) (0) +#endif +/* Cleanups are always exported in 2017.4, and some git releases between 2017.3 and 2017.4. + We actually check against 2017.3 so that we work on the git releases *after* 2017.3 + which is safe, because the real OSTREE_CHECK_VERSION macro was added after 2017.3 + too. */ +#if !OSTREE_CHECK_VERSION(2017, 3) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoCommitModifier, ostree_repo_commit_modifier_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoDevInoCache, ostree_repo_devino_cache_unref) +#endif + +#ifndef SOUP_AUTOCLEANUPS_H +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupSession, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupMessage, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupRequest, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupRequestHTTP, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupURI, soup_uri_free) +#endif + +#if !JSON_CHECK_VERSION(1,1,2) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonArray, json_array_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonBuilder, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonGenerator, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonNode, json_node_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonObject, json_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonParser, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonPath, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonReader, g_object_unref) +#endif + +#if !GLIB_CHECK_VERSION(2, 43, 4) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUnixFDList, g_object_unref) +#endif + +/* This uses a weird Auto prefix to avoid conflicts with later added autogenerated autoptr support, per: + * https://git.gnome.org/browse/glib/commit/?id=1c6cd5f0a3104aa9b62c7f1d3086181f63e71b59 + */ +typedef FlatpakSessionHelper AutoFlatpakSessionHelper; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoFlatpakSessionHelper, g_object_unref) + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (XdpDbusDocuments, g_object_unref) + +typedef struct FlatpakXml FlatpakXml; + +struct FlatpakXml +{ + gchar *element_name; /* NULL == text */ + char **attribute_names; + char **attribute_values; + char *text; + FlatpakXml *parent; + FlatpakXml *first_child; + FlatpakXml *last_child; + FlatpakXml *next_sibling; +}; + +FlatpakXml *flatpak_xml_new (const gchar *element_name); +FlatpakXml *flatpak_xml_new_text (const gchar *text); +void flatpak_xml_add (FlatpakXml *parent, + FlatpakXml *node); +void flatpak_xml_free (FlatpakXml *node); +FlatpakXml *flatpak_xml_parse (GInputStream *in, + gboolean compressed, + GCancellable *cancellable, + GError **error); +void flatpak_xml_to_string (FlatpakXml *node, + GString *res); +FlatpakXml *flatpak_xml_unlink (FlatpakXml *node, + FlatpakXml *prev_sibling); +FlatpakXml *flatpak_xml_find (FlatpakXml *node, + const char *type, + FlatpakXml **prev_child_out); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakXml, flatpak_xml_free); + +FlatpakXml *flatpak_appstream_xml_new (void); +gboolean flatpak_appstream_xml_migrate (FlatpakXml *source, + FlatpakXml *dest, + const char *ref, + const char *id, + GKeyFile *metadata); +gboolean flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root, + GBytes **uncompressed, + GBytes **compressed, + GError **error); +gboolean flatpak_repo_generate_appstream (OstreeRepo *repo, + const char **gpg_key_ids, + const char *gpg_homedir, + guint64 timestamp, + GCancellable *cancellable, + GError **error); + +gboolean flatpak_allocate_tmpdir (int tmpdir_dfd, + const char *tmpdir_relpath, + const char *tmpdir_prefix, + char **tmpdir_name_out, + int *tmpdir_fd_out, + GLnxLockFile *file_lock_out, + gboolean *reusing_dir_out, + GCancellable *cancellable, + GError **error); + + +gboolean flatpak_yes_no_prompt (const char *prompt, ...) G_GNUC_PRINTF(1, 2); +long flatpak_number_prompt (int min, int max, const char *prompt, ...) G_GNUC_PRINTF(3, 4); + +SoupSession * flatpak_create_soup_session (const char *user_agent); + +typedef enum { + FLATPAK_HTTP_FLAGS_NONE = 0, + FLATPAK_HTTP_FLAGS_ACCEPT_OCI = 1<<0, +} FlatpakHTTPFlags; + +GBytes * flatpak_load_http_uri (SoupSession *soup_session, + const char *uri, + FlatpakHTTPFlags flags, + const char *etag, + char **out_etag, + FlatpakLoadUriProgress progress, + gpointer user_data, + GCancellable *cancellable, + GError **error); +gboolean flatpak_download_http_uri (SoupSession *soup_session, + const char *uri, + FlatpakHTTPFlags flags, + GOutputStream *out, + FlatpakLoadUriProgress progress, + gpointer user_data, + GCancellable *cancellable, + GError **error); + +typedef void (*FlatpakProgressCallback)(const char *status, + guint progress, + gboolean estimating, + gpointer user_data); + +OstreeAsyncProgress *flatpak_progress_new (FlatpakProgressCallback progress, + gpointer progress_data); + +void flatpak_log_dir_access (FlatpakDir *dir); + +gboolean flatpak_check_required_version (const char *ref, + GKeyFile *metakey, + GError **error); + +#endif /* __FLATPAK_UTILS_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-version-macros.h flatpak-0.11.8.3/common/flatpak-version-macros.h --- flatpak-0.11.7/common/flatpak-version-macros.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-version-macros.h 2018-06-13 11:39:44.000000000 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright © 2015 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 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined (__FLATPAK_H_INSIDE__) && !defined (FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_VERSION_MACROS_H__ +#define __FLATPAK_VERSION_MACROS_H__ + +#define FLATPAK_MAJOR_VERSION (0) +#define FLATPAK_MINOR_VERSION (11) +#define FLATPAK_MICRO_VERSION (8) + +#define FLATPAK_CHECK_VERSION(major,minor,micro) \ + (FLATPAK_MAJOR_VERSION > (major) || \ + (FLATPAK_MAJOR_VERSION == (major) && FLATPAK_MINOR_VERSION > (minor)) || \ + (FLATPAK_MAJOR_VERSION == (major) && FLATPAK_MINOR_VERSION == (minor) && \ + FLATPAK_MICRO_VERSION >= (micro))) + +#ifndef FLATPAK_EXTERN +#define FLATPAK_EXTERN extern +#endif + +/** + * SECTION:flatpak-version-macros + * @Title: Version information + */ + +#endif /* __FLATPAK_VERSION_MACROS_H__ */ diff -Nru flatpak-0.11.7/common/flatpak-version-macros.h.in flatpak-0.11.8.3/common/flatpak-version-macros.h.in --- flatpak-0.11.7/common/flatpak-version-macros.h.in 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/flatpak-version-macros.h.in 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright © 2015 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 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 . + * + * Authors: + * Alexander Larsson + */ + +#if !defined (__FLATPAK_H_INSIDE__) && !defined (FLATPAK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __FLATPAK_VERSION_MACROS_H__ +#define __FLATPAK_VERSION_MACROS_H__ + +#define FLATPAK_MAJOR_VERSION (@FLATPAK_MAJOR_VERSION@) +#define FLATPAK_MINOR_VERSION (@FLATPAK_MINOR_VERSION@) +#define FLATPAK_MICRO_VERSION (@FLATPAK_MICRO_VERSION@) + +#define FLATPAK_CHECK_VERSION(major,minor,micro) \ + (FLATPAK_MAJOR_VERSION > (major) || \ + (FLATPAK_MAJOR_VERSION == (major) && FLATPAK_MINOR_VERSION > (minor)) || \ + (FLATPAK_MAJOR_VERSION == (major) && FLATPAK_MINOR_VERSION == (minor) && \ + FLATPAK_MICRO_VERSION >= (micro))) + +#ifndef FLATPAK_EXTERN +#define FLATPAK_EXTERN extern +#endif + +/** + * SECTION:flatpak-version-macros + * @Title: Version information + */ + +#endif /* __FLATPAK_VERSION_MACROS_H__ */ diff -Nru flatpak-0.11.7/common/Makefile.am.inc flatpak-0.11.8.3/common/Makefile.am.inc --- flatpak-0.11.7/common/Makefile.am.inc 2018-04-26 08:29:28.000000000 +0100 +++ flatpak-0.11.8.3/common/Makefile.am.inc 2018-06-11 14:52:37.000000000 +0100 @@ -1,76 +1,128 @@ +lib_LTLIBRARIES += libflatpak.la noinst_LTLIBRARIES += libflatpak-common.la +noinst_PROGRAMS += test-libflatpak -dbus_built_sources = common/flatpak-dbus.c common/flatpak-dbus.h common/flatpak-document-dbus.c common/flatpak-document-dbus.h -systemd_dbus_built_sources = common/flatpak-systemd-dbus.c common/flatpak-systemd-dbus.h +flatpakincludedir = $(includedir)/flatpak -common/flatpak-dbus.c: data/org.freedesktop.Flatpak.xml Makefile +flatpakinclude_HEADERS = \ + common/flatpak.h \ + common/flatpak-ref.h \ + common/flatpak-error.h \ + common/flatpak-installed-ref.h \ + common/flatpak-remote-ref.h \ + common/flatpak-related-ref.h \ + common/flatpak-bundle-ref.h \ + common/flatpak-installation.h \ + common/flatpak-remote.h \ + common/flatpak-version-macros.h \ + common/flatpak-portal-error.h \ + common/flatpak-transaction.h \ + $(NULL) + +nodist_flatpakinclude_HEADERS = \ + common/flatpak-enum-types.h \ + $(NULL) + +dbus_built_sources = common/flatpak-dbus-generated.c common/flatpak-dbus-generated.h common/flatpak-document-dbus-generated.c common/flatpak-document-dbus-generated.h +systemd_dbus_built_sources = common/flatpak-systemd-dbus-generated.c common/flatpak-systemd-dbus-generated.h + +common/flatpak-enum-types.h: $(flatpakinclude_HEADERS) common/flatpak-enum-types.h.template + $(AM_V_GEN) $(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \ + common/flatpak-enum-types.h.tmp && mv common/flatpak-enum-types.h.tmp common/flatpak-enum-types.h + +common/flatpak-enum-types.c: $(flatpakinclude_HEADERS) common/flatpak-enum-types.c.template + $(AM_V_GEN) $(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \ + common/flatpak-enum-types.c.tmp && mv common/flatpak-enum-types.c.tmp common/flatpak-enum-types.c + +EXTRA_DIST += common/flatpak-enum-types.c.template common/flatpak-enum-types.h.template + +common/flatpak-dbus-generated.c: data/org.freedesktop.Flatpak.xml Makefile mkdir -p $(builddir)/common $(AM_V_GEN) $(GDBUS_CODEGEN) \ --interface-prefix org.freedesktop.Flatpak. \ --c-namespace Flatpak \ - --generate-c-code $(builddir)/common/flatpak-dbus \ + --generate-c-code $(builddir)/common/flatpak-dbus-generated \ $(srcdir)/data/org.freedesktop.Flatpak.xml \ $(NULL) -common/flatpak-document-dbus.c: data/org.freedesktop.portal.Documents.xml Makefile +common/flatpak-document-dbus-generated.c: data/org.freedesktop.portal.Documents.xml Makefile mkdir -p $(builddir)/common $(AM_V_GEN) $(GDBUS_CODEGEN) \ --interface-prefix org.freedesktop.portal. \ --c-namespace XdpDbus \ - --generate-c-code $(builddir)/common/flatpak-document-dbus \ + --generate-c-code $(builddir)/common/flatpak-document-dbus-generated \ $(srcdir)/data/org.freedesktop.portal.Documents.xml \ $(NULL) -common/flatpak-systemd-dbus.c: data/org.freedesktop.systemd1.xml Makefile +common/flatpak-systemd-dbus-generated.c: data/org.freedesktop.systemd1.xml Makefile mkdir -p $(builddir)/common $(AM_V_GEN) $(GDBUS_CODEGEN) \ --interface-prefix org.freedesktop.systemd1. \ --c-namespace Systemd \ - --generate-c-code $(builddir)/common/flatpak-systemd-dbus \ + --generate-c-code $(builddir)/common/flatpak-systemd-dbus-generated \ $(srcdir)/data/org.freedesktop.systemd1.xml \ $(NULL) -common/%-dbus.h: common/%-dbus.c +common/%-dbus-generated.h: common/%-dbus-generated.c @true # Built as a side-effect of the rules for the .c nodist_libflatpak_common_la_SOURCES = \ + $(nodist_flatpakinclude_HEADERS) \ $(dbus_built_sources) \ $(systemd_dbus_built_sources) \ $(xdp_dbus_built_sources) \ + common/flatpak-enum-types.c \ $(NULL) BUILT_SOURCES += $(nodist_libflatpak_common_la_SOURCES) CLEANFILES += $(nodist_libflatpak_common_la_SOURCES) libflatpak_common_la_SOURCES = \ - common/flatpak-common-types.h \ + $(flatpakinclude_HEADERS) \ + common/flatpak-common-types-private.h \ common/flatpak-bwrap.c \ - common/flatpak-bwrap.h \ + common/flatpak-bwrap-private.h \ common/flatpak-dir.c \ - common/flatpak-dir.h \ + common/flatpak-dir-private.h \ common/flatpak-run.c \ - common/flatpak-run.h \ + common/flatpak-run-private.h \ common/flatpak-context.c \ - common/flatpak-context.h \ + common/flatpak-context-private.h \ common/flatpak-exports.c \ - common/flatpak-exports.h \ + common/flatpak-exports-private.h \ + common/flatpak-transaction-private.h \ + common/flatpak-transaction.h \ + common/flatpak-transaction.c \ common/flatpak-utils.c \ - common/flatpak-utils.h \ - common/flatpak-table-printer.c \ - common/flatpak-table-printer.h \ + common/flatpak-utils-private.h \ common/flatpak-chain-input-stream.c \ - common/flatpak-chain-input-stream.h \ + common/flatpak-chain-input-stream-private.h \ common/flatpak-portal-error.c \ common/flatpak-portal-error.h \ common/flatpak-json.c \ - common/flatpak-json.h \ + common/flatpak-json-private.h \ common/flatpak-json-oci.c \ - common/flatpak-json-oci.h \ + common/flatpak-json-oci-private.h \ common/flatpak-oci-registry.c \ - common/flatpak-oci-registry.h \ + common/flatpak-oci-registry-private.h \ + common/flatpak-ref.c \ + common/flatpak-installed-ref.c \ + common/flatpak-installed-ref-private.h \ + common/flatpak-remote-ref.c \ + common/flatpak-remote-ref-private.h \ + common/flatpak-bundle-ref.c \ + common/flatpak-related-ref.c \ + common/flatpak-related-ref-private.h \ + common/flatpak-remote-private.h \ + common/flatpak-remote.c \ + common/flatpak-error.c \ + common/flatpak-installation-private.h \ + common/flatpak-installation.c \ + common/valgrind-private.h \ $(NULL) libflatpak_common_la_CFLAGS = \ + -DFLATPAK_COMPILATION \ $(AM_CFLAGS) \ $(BASE_CFLAGS) \ $(HIDDEN_VISIBILITY_CFLAGS) \ @@ -83,3 +135,92 @@ -I$(srcdir)/dbus-proxy \ $(NULL) libflatpak_common_la_LIBADD = $(AM_LIBADD) libglnx.la $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(JSON_LIBS) $(XAUTH_LIBS) $(LIBSECCOMP_LIBS) $(INTERNAL_GPGME_LIBS) + + +libflatpak_la_SOURCES = \ + common/flatpak.c \ + $(NULL) + +libflatpak_la_CFLAGS = \ + $(HIDDEN_VISIBILITY_CFLAGS) \ + -DFLATPAK_COMPILATION \ + -I$(top_srcdir)/common \ + -I$(top_builddir)/common \ + $(AM_CFLAGS) \ + $(BASE_CFLAGS) \ + $(OSTREE_CFLAGS) \ + $(SOUP_CFLAGS) \ + $(JSON_CFLAGS) \ + $(NULL) + +libflatpak_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -version-info $(LT_VERSION_INFO) \ + -export-dynamic \ + -rpath $(libdir) \ + $(NULL) + +libflatpak_la_LIBADD = \ + $(AM_LIBADD) \ + libflatpak-common.la \ + $(BASE_LIBS) \ + $(OSTREE_LIBS) \ + $(SOUP_LIBS) \ + $(JSON_LIBS) \ + $(NULL) + +test_libflatpak_SOURCES = \ + common/test-lib.c \ + $(NULL) + +test_libflatpak_CFLAGS = \ + $(AM_CFLAGS) \ + $(BASE_CFLAGS) \ + -I$(top_srcdir)/common \ + -I$(top_builddir)/common \ + $(NULL) + +test_libflatpak_LDADD = \ + $(AM_LDADD) \ + $(BASE_LIBS) \ + libflatpak.la \ + $(NULL) + +# gobject-introspection rules +-include $(INTROSPECTION_MAKEFILE) + +sources = $(libflatpak_common_la_SOURCES) $(libflatpak_la_SOURCES) + +INTROSPECTION_GIRS = + +if HAVE_INTROSPECTION +Flatpak-1.0.gir: libflatpak.la Makefile + +introspected_headers = \ + $(flatpakinclude_HEADERS) \ + $(nodist_flatpakinclude_HEADERS) \ + $(NULL) +introspected_sources = $(filter-out %-private.h,$(sources)) + +Flatpak_1_0_gir_NAMESPACE = Flatpak +Flatpak_1_0_gir_VERSION = 1.0 +Flatpak_1_0_gir_LIBS = libflatpak.la +Flatpak_1_0_gir_FILES = $(introspected_headers) $(introspected_sources) +Flatpak_1_0_gir_CFLAGS = $(libflatpak_la_CFLAGS) +Flatpak_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0 +Flatpak_1_0_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='flatpak.h' \ + --pkg-export=flatpak + +INTROSPECTION_GIRS += Flatpak-1.0.gir + +girdir = $(datadir)/gir-1.0 +nodist_gir_DATA = $(INTROSPECTION_GIRS) +CLEANFILES += $(nodist_gir_DATA) + +typelibdir = $(libdir)/girepository-1.0 +nodist_typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +CLEANFILES += $(nodist_typelib_DATA) + +endif # HAVE_INTROSPECTION diff -Nru flatpak-0.11.7/common/test-lib.c flatpak-0.11.8.3/common/test-lib.c --- flatpak-0.11.7/common/test-lib.c 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/test-lib.c 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,457 @@ +#include "config.h" + +#include "libglnx/libglnx.h" + +#include +#include + + +static void +progress_cb (const char *status, + guint progress, + gboolean estimating, + gpointer user_data) +{ + g_print ("status: %s, progress: %d estimating: %d, user_data: %p\n", status, progress, estimating, user_data); +} + +static gboolean +monitor_callback (GFileMonitor * monitor, + GFile * child, + GFile * other_file, + GFileMonitorEvent eflags) +{ + g_print ("Database changed\n"); + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + FlatpakInstallation *installation; + FlatpakInstalledRef *app1; + FlatpakInstalledRef *app2; + FlatpakRemoteRef *remote_ref; + + g_autoptr(GPtrArray) remotes = NULL; + GError *error = NULL; + int i, j, k; + + installation = flatpak_installation_new_user (NULL, &error); + if (installation == NULL) + { + g_print ("error: %s\n", error->message); + return 1; + } + + if (0) + { + const char *list[] = { "gnome-apps", "app/org.gnome.iagno/x86_64/stable", + "gnome", "runtime/org.gnome.Sdk/x86_64/3.20" }; + + for (j = 0; j < G_N_ELEMENTS(list); j += 2) + { + g_print ("looking for related to ref: %s\n", list[j+1]); + + for (k = 0; k < 2; k++) + { + g_autoptr(GError) error = NULL; + g_autoptr(GPtrArray) related = NULL; + + + if (k == 0) + related = flatpak_installation_list_remote_related_refs_sync (installation, + list[j], + list[j+1], + NULL, + &error); + else + related = flatpak_installation_list_installed_related_refs_sync (installation, + list[j], + list[j+1], + NULL, + &error); + + if (related == NULL) + { + g_warning ("Error: %s", error->message); + continue; + } + + g_print ("%s related:\n", (k == 0) ? "remote" : "local"); + for (i = 0; i < related->len; i++) + { + FlatpakRelatedRef *rel = g_ptr_array_index (related, i); + const char * const *subpaths = flatpak_related_ref_get_subpaths (rel); + g_autofree char *subpaths_str = NULL; + + if (subpaths) + { + g_autofree char *subpaths_joined = g_strjoinv (",", (char **) subpaths); + subpaths_str = g_strdup_printf (" subpaths: %s", subpaths_joined); + } + else + subpaths_str = g_strdup (""); + g_print ("%d %s %s %s %s dl:%d del:%d%s\n", + flatpak_ref_get_kind (FLATPAK_REF (rel)), + flatpak_ref_get_name (FLATPAK_REF (rel)), + flatpak_ref_get_arch (FLATPAK_REF (rel)), + flatpak_ref_get_branch (FLATPAK_REF (rel)), + flatpak_ref_get_commit (FLATPAK_REF (rel)), + flatpak_related_ref_should_download (rel), + flatpak_related_ref_should_delete (rel), + subpaths_str); + } + } + } + + return 0; + } + + if (argc == 4) + { + GFileMonitor * monitor = flatpak_installation_create_monitor (installation, NULL, NULL); + GMainLoop *main_loop; + + g_signal_connect (monitor, "changed", (GCallback) monitor_callback, NULL); + main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (main_loop); + } + + if (argc == 3) + { + app1 = flatpak_installation_install (installation, + argv[1], + FLATPAK_REF_KIND_APP, + argv[2], + NULL, NULL, + progress_cb, (gpointer) 0xdeadbeef, + NULL, &error); + if (app1 == NULL) + g_print ("Error: %s\n", error->message); + else + g_print ("Installed %s: %s\n", argv[2], + flatpak_ref_get_commit (FLATPAK_REF (app1))); + + return 0; + } + + if (argc == 2) + { + app1 = flatpak_installation_update (installation, + FLATPAK_UPDATE_FLAGS_NONE, + FLATPAK_REF_KIND_APP, + argv[1], + NULL, NULL, + progress_cb, (gpointer) 0xdeadbeef, + NULL, &error); + if (app1 == NULL) + g_print ("Error: %s\n", error->message); + else + g_print ("Updated %s: %s\n", argv[1], + flatpak_ref_get_commit (FLATPAK_REF (app1))); + + return 0; + } + + g_print ("\n**** Loading bundle\n"); + { + g_autoptr(GFile) f = g_file_new_for_commandline_arg ("tests/hello.pak"); + g_autoptr(FlatpakBundleRef) bundle = flatpak_bundle_ref_new (f, &error); + if (bundle == NULL) + { + g_print ("Error loading bundle: %s\n", error->message); + g_clear_error (&error); + } + else + { + g_autofree char *path = g_file_get_path (flatpak_bundle_ref_get_file (bundle)); + g_autoptr(GBytes) metadata = flatpak_bundle_ref_get_metadata (bundle); + g_autoptr(GBytes) appdata = flatpak_bundle_ref_get_appstream (bundle); + g_print ("%d %s %s %s %s %s %"G_GUINT64_FORMAT "\n%s\n", + flatpak_ref_get_kind (FLATPAK_REF (bundle)), + flatpak_ref_get_name (FLATPAK_REF (bundle)), + flatpak_ref_get_arch (FLATPAK_REF (bundle)), + flatpak_ref_get_branch (FLATPAK_REF (bundle)), + flatpak_ref_get_commit (FLATPAK_REF (bundle)), + path, + flatpak_bundle_ref_get_installed_size (bundle), + (char *) g_bytes_get_data (metadata, NULL)); + + if (appdata != NULL) + { + g_autoptr(GZlibDecompressor) decompressor = NULL; + g_autoptr(GOutputStream) out2 = NULL; + g_autoptr(GOutputStream) out = NULL; + + out = g_unix_output_stream_new (1, FALSE); + decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); + out2 = g_converter_output_stream_new (out, G_CONVERTER (decompressor)); + + if (!g_output_stream_write_all (out2, + g_bytes_get_data (appdata, NULL), + g_bytes_get_size (appdata), + NULL, NULL, &error)) + { + g_print ("Error decompressing appdata: %s\n", error->message); + g_clear_error (&error); + } + } + } + } + + g_print ("\n**** Checking for updates\n"); + { + g_autoptr(GPtrArray) updates = + flatpak_installation_list_installed_refs_for_update (installation, + NULL, &error); + + if (updates == NULL) + { + g_print ("check for updates error: %s\n", error->message); + g_clear_error (&error); + } + else + { + for (i = 0; i < updates->len; i++) + { + FlatpakInstalledRef *ref = g_ptr_array_index (updates, i); + g_print ("%d %s %s %s %s %s %s %s %d %"G_GUINT64_FORMAT "\n", + flatpak_ref_get_kind (FLATPAK_REF (ref)), + flatpak_ref_get_name (FLATPAK_REF (ref)), + flatpak_ref_get_arch (FLATPAK_REF (ref)), + flatpak_ref_get_branch (FLATPAK_REF (ref)), + flatpak_ref_get_commit (FLATPAK_REF (ref)), + flatpak_installed_ref_get_latest_commit (ref), + flatpak_installed_ref_get_origin (ref), + flatpak_installed_ref_get_deploy_dir (ref), + flatpak_installed_ref_get_is_current (ref), + flatpak_installed_ref_get_installed_size (ref)); + } + } + } + + g_print ("\n**** Listing all installed refs\n"); + { + g_autoptr(GPtrArray) refs = NULL; + + refs = flatpak_installation_list_installed_refs (installation, + NULL, NULL); + + for (i = 0; i < refs->len; i++) + { + FlatpakInstalledRef *ref = g_ptr_array_index (refs, i); + g_print ("%d %s %s %s %s %s %s %s %d %"G_GUINT64_FORMAT "\n", + flatpak_ref_get_kind (FLATPAK_REF (ref)), + flatpak_ref_get_name (FLATPAK_REF (ref)), + flatpak_ref_get_arch (FLATPAK_REF (ref)), + flatpak_ref_get_branch (FLATPAK_REF (ref)), + flatpak_ref_get_commit (FLATPAK_REF (ref)), + flatpak_installed_ref_get_latest_commit (ref), + flatpak_installed_ref_get_origin (ref), + flatpak_installed_ref_get_deploy_dir (ref), + flatpak_installed_ref_get_is_current (ref), + flatpak_installed_ref_get_installed_size (ref)); + } + } + + g_print ("**** Listing all installed apps\n"); + { + g_autoptr(GPtrArray) apps = NULL; + + apps = flatpak_installation_list_installed_refs_by_kind (installation, + FLATPAK_REF_KIND_APP, + NULL, NULL); + + for (i = 0; i < apps->len; i++) + { + FlatpakInstalledRef *app = g_ptr_array_index (apps, i); + + g_print ("%d %s %s %s %s %s %s %s %d %"G_GUINT64_FORMAT "\n", + flatpak_ref_get_kind (FLATPAK_REF (app)), + flatpak_ref_get_name (FLATPAK_REF (app)), + flatpak_ref_get_arch (FLATPAK_REF (app)), + flatpak_ref_get_branch (FLATPAK_REF (app)), + flatpak_ref_get_commit (FLATPAK_REF (app)), + flatpak_installed_ref_get_latest_commit (app), + flatpak_installed_ref_get_origin (app), + flatpak_installed_ref_get_deploy_dir (app), + flatpak_installed_ref_get_is_current (app), + flatpak_installed_ref_get_installed_size (app)); + g_print ("metadata:\n%s\n", (char *) g_bytes_get_data (flatpak_installed_ref_load_metadata (app, NULL, NULL), NULL)); + } + } + + g_print ("\n**** Listing all installed runtimes\n"); + { + g_autoptr(GPtrArray) runtimes = NULL; + + runtimes = flatpak_installation_list_installed_refs_by_kind (installation, + FLATPAK_REF_KIND_RUNTIME, + NULL, NULL); + + for (i = 0; i < runtimes->len; i++) + { + FlatpakInstalledRef *runtime = g_ptr_array_index (runtimes, i); + g_print ("%d %s %s %s %s %s %s %d\n", + flatpak_ref_get_kind (FLATPAK_REF (runtime)), + flatpak_ref_get_name (FLATPAK_REF (runtime)), + flatpak_ref_get_arch (FLATPAK_REF (runtime)), + flatpak_ref_get_branch (FLATPAK_REF (runtime)), + flatpak_ref_get_commit (FLATPAK_REF (runtime)), + flatpak_installed_ref_get_origin (runtime), + flatpak_installed_ref_get_deploy_dir (runtime), + flatpak_installed_ref_get_is_current (runtime)); + } + } + + g_print ("\n**** Getting installed gedit master\n"); + app1 = flatpak_installation_get_installed_ref (installation, + FLATPAK_REF_KIND_APP, + "org.gnome.gedit", + NULL, "master", NULL, NULL); + if (app1) + { + g_print ("gedit master: %d %s %s %s %s %s %s %d\n", + flatpak_ref_get_kind (FLATPAK_REF (app1)), + flatpak_ref_get_name (FLATPAK_REF (app1)), + flatpak_ref_get_arch (FLATPAK_REF (app1)), + flatpak_ref_get_branch (FLATPAK_REF (app1)), + flatpak_ref_get_commit (FLATPAK_REF (app1)), + flatpak_installed_ref_get_origin (app1), + flatpak_installed_ref_get_deploy_dir (app1), + flatpak_installed_ref_get_is_current (app1)); + } + if (!flatpak_installation_launch (installation, + "org.gnome.gedit", + NULL, NULL, NULL, + NULL, &error)) + { + g_print ("launch gedit error: %s\n", error->message); + g_clear_error (&error); + } + + g_print ("\n**** Getting current installed gedit\n"); + app2 = flatpak_installation_get_current_installed_app (installation, + "org.gnome.gedit", + NULL, NULL); + if (app2) + { + g_print ("gedit current: %d %s %s %s %s %s %s %d\n", + flatpak_ref_get_kind (FLATPAK_REF (app2)), + flatpak_ref_get_name (FLATPAK_REF (app2)), + flatpak_ref_get_arch (FLATPAK_REF (app2)), + flatpak_ref_get_branch (FLATPAK_REF (app2)), + flatpak_ref_get_commit (FLATPAK_REF (app2)), + flatpak_installed_ref_get_origin (app2), + flatpak_installed_ref_get_deploy_dir (app2), + flatpak_installed_ref_get_is_current (app2)); + } + + + g_print ("\n**** Listing remotes\n"); + remotes = flatpak_installation_list_remotes (installation, + NULL, NULL); + + for (i = 0; i < remotes->len; i++) + { + FlatpakRemote *remote = g_ptr_array_index (remotes, i); + g_autoptr(GPtrArray) refs = NULL; + const char *collection_id = NULL; + +#ifdef FLATPAK_ENABLE_P2P + collection_id = flatpak_remote_get_collection_id (remote); +#endif /* !FLATPAK_ENABLE_P2P */ + + g_print ("\nRemote: %s %u %d %s %s %s %s %d %d %s\n", + flatpak_remote_get_name (remote), + flatpak_remote_get_remote_type (remote), + flatpak_remote_get_prio (remote), + flatpak_remote_get_url (remote), + collection_id, + flatpak_remote_get_title (remote), + flatpak_remote_get_default_branch (remote), + flatpak_remote_get_gpg_verify (remote), + flatpak_remote_get_noenumerate (remote), + g_file_get_path (flatpak_remote_get_appstream_dir (remote, NULL))); + + g_print ("\n**** Listing remote refs on %s\n", flatpak_remote_get_name (remote)); + refs = flatpak_installation_list_remote_refs_sync (installation, flatpak_remote_get_name (remote), + NULL, NULL); + if (refs) + { + for (j = 0; j < refs->len; j++) + { + FlatpakRemoteRef *ref = g_ptr_array_index (refs, j); + g_print ("%d %s %s %s %s %s\n", + flatpak_ref_get_kind (FLATPAK_REF (ref)), + flatpak_ref_get_name (FLATPAK_REF (ref)), + flatpak_ref_get_arch (FLATPAK_REF (ref)), + flatpak_ref_get_branch (FLATPAK_REF (ref)), + flatpak_ref_get_commit (FLATPAK_REF (ref)), + flatpak_remote_ref_get_remote_name (ref)); + + if (j == 0) + { + guint64 download_size; + guint64 installed_size; + + if (!flatpak_installation_fetch_remote_size_sync (installation, + flatpak_remote_get_name (remote), + FLATPAK_REF (ref), + &download_size, + &installed_size, + NULL, &error)) + { + g_print ("error fetching sizes: %s\n", error->message); + g_clear_error (&error); + } + else + { + g_print ("Download size: %"G_GUINT64_FORMAT " Installed size: %"G_GUINT64_FORMAT "\n", + download_size, installed_size); + } + + } + } + } + + g_print ("\n**** Getting remote platform 3.20 on %s\n", flatpak_remote_get_name (remote)); + error = NULL; + remote_ref = flatpak_installation_fetch_remote_ref_sync (installation, flatpak_remote_get_name (remote), + FLATPAK_REF_KIND_RUNTIME, + "org.gnome.Platform", NULL, "3.20", + NULL, &error); + if (remote_ref) + { + GBytes *metadata; + + g_print ("%d %s %s %s %s %s\n", + flatpak_ref_get_kind (FLATPAK_REF (remote_ref)), + flatpak_ref_get_name (FLATPAK_REF (remote_ref)), + flatpak_ref_get_arch (FLATPAK_REF (remote_ref)), + flatpak_ref_get_branch (FLATPAK_REF (remote_ref)), + flatpak_ref_get_commit (FLATPAK_REF (remote_ref)), + flatpak_remote_ref_get_remote_name (remote_ref)); + + metadata = flatpak_installation_fetch_remote_metadata_sync (installation, flatpak_remote_get_name (remote), + FLATPAK_REF (remote_ref), NULL, &error); + if (metadata) + { + g_print ("metadata: %s\n", (char *) g_bytes_get_data (metadata, NULL)); + } + else + { + g_print ("fetch error\n"); + g_print ("error: %s\n", error->message); + g_clear_error (&error); + } + } + else + { + g_print ("error: %s\n", error->message); + g_clear_error (&error); + } + } + return 0; +} diff -Nru flatpak-0.11.7/common/valgrind-private.h flatpak-0.11.8.3/common/valgrind-private.h --- flatpak-0.11.7/common/valgrind-private.h 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/common/valgrind-private.h 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,6644 @@ +/* -*- c -*- + ---------------------------------------------------------------- + + Notice that the following BSD-style license applies to this one + file (valgrind.h) only. The rest of Valgrind is licensed under the + terms of the GNU General Public License, version 2, unless + otherwise indicated. See the COPYING file in the source + distribution for details. + + ---------------------------------------------------------------- + + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2017 Julian Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ---------------------------------------------------------------- + + Notice that the above BSD-style license applies to this one file + (valgrind.h) only. The entire rest of Valgrind is licensed under + the terms of the GNU General Public License, version 2. See the + COPYING file in the source distribution for details. + + ---------------------------------------------------------------- +*/ + + +/* This file is for inclusion into client (your!) code. + + You can use these macros to manipulate and query Valgrind's + execution inside your own programs. + + The resulting executables will still run without Valgrind, just a + little bit more slowly than they otherwise would, but otherwise + unchanged. When not running on valgrind, each client request + consumes very few (eg. 7) instructions, so the resulting performance + loss is negligible unless you plan to execute client requests + millions of times per second. Nevertheless, if that is still a + problem, you can compile with the NVALGRIND symbol defined (gcc + -DNVALGRIND) so that client requests are not even compiled in. */ + +#ifndef __VALGRIND_H +#define __VALGRIND_H + + +/* ------------------------------------------------------------------ */ +/* VERSION NUMBER OF VALGRIND */ +/* ------------------------------------------------------------------ */ + +/* Specify Valgrind's version number, so that user code can + conditionally compile based on our version number. Note that these + were introduced at version 3.6 and so do not exist in version 3.5 + or earlier. The recommended way to use them to check for "version + X.Y or later" is (eg) + +#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ + && (__VALGRIND_MAJOR__ > 3 \ + || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) +*/ +#define __VALGRIND_MAJOR__ 3 +#define __VALGRIND_MINOR__ 13 + + +#include + +/* Nb: this file might be included in a file compiled with -ansi. So + we can't use C++ style "//" comments nor the "asm" keyword (instead + use "__asm__"). */ + +/* Derive some tags indicating what the target platform is. Note + that in this file we're using the compiler's CPP symbols for + identifying architectures, which are different to the ones we use + within the rest of Valgrind. Note, __powerpc__ is active for both + 32 and 64-bit PPC, whereas __powerpc64__ is only active for the + latter (on Linux, that is). + + Misc note: how to find out what's predefined in gcc by default: + gcc -Wp,-dM somefile.c +*/ +#undef PLAT_x86_darwin +#undef PLAT_amd64_darwin +#undef PLAT_x86_win32 +#undef PLAT_amd64_win64 +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64be_linux +#undef PLAT_ppc64le_linux +#undef PLAT_arm_linux +#undef PLAT_arm64_linux +#undef PLAT_s390x_linux +#undef PLAT_mips32_linux +#undef PLAT_mips64_linux +#undef PLAT_x86_solaris +#undef PLAT_amd64_solaris + + +#if defined(__APPLE__) && defined(__i386__) +# define PLAT_x86_darwin 1 +#elif defined(__APPLE__) && defined(__x86_64__) +# define PLAT_amd64_darwin 1 +#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \ + || defined(__CYGWIN32__) \ + || (defined(_WIN32) && defined(_M_IX86)) +# define PLAT_x86_win32 1 +#elif defined(__MINGW64__) \ + || (defined(_WIN64) && defined(_M_X64)) +# define PLAT_amd64_win64 1 +#elif defined(__linux__) && defined(__i386__) +# define PLAT_x86_linux 1 +#elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__) +# define PLAT_amd64_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) +# define PLAT_ppc32_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2 +/* Big Endian uses ELF version 1 */ +# define PLAT_ppc64be_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2 +/* Little Endian uses ELF version 2 */ +# define PLAT_ppc64le_linux 1 +#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__) +# define PLAT_arm_linux 1 +#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__) +# define PLAT_arm64_linux 1 +#elif defined(__linux__) && defined(__s390__) && defined(__s390x__) +# define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) && (__mips==64) +# define PLAT_mips64_linux 1 +#elif defined(__linux__) && defined(__mips__) && (__mips!=64) +# define PLAT_mips32_linux 1 +#elif defined(__sun) && defined(__i386__) +# define PLAT_x86_solaris 1 +#elif defined(__sun) && defined(__x86_64__) +# define PLAT_amd64_solaris 1 +#else +/* If we're not compiling for our target platform, don't generate + any inline asms. */ +# if !defined(NVALGRIND) +# define NVALGRIND 1 +# endif +#endif + + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ +/* in here of use to end-users -- skip to the next section. */ +/* ------------------------------------------------------------------ */ + +/* + * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client + * request. Accepts both pointers and integers as arguments. + * + * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind + * client request that does not return a value. + + * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind + * client request and whose value equals the client request result. Accepts + * both pointers and integers as arguments. Note that such calls are not + * necessarily pure functions -- they may have side effects. + */ + +#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \ + _zzq_request, _zzq_arg1, _zzq_arg2, \ + _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \ + (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ + (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) + +#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \ + _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ + (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) + +#if defined(NVALGRIND) + +/* Define NVALGRIND to completely remove the Valgrind magic sequence + from the compiled code (analogous to NDEBUG's effects on + assert()) */ +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + (_zzq_default) + +#else /* ! NVALGRIND */ + +/* The following defines the magic code sequences which the JITter + spots and handles magically. Don't look too closely at them as + they will rot your brain. + + The assembly code sequences for all architectures is in this one + file. This is because this file must be stand-alone, and we don't + want to have multiple files. + + For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default + value gets put in the return slot, so that everything works when + this is executed not under Valgrind. Args are passed in a memory + block, and so there's no intrinsic limit to the number that could + be passed, but it's currently five. + + The macro args are: + _zzq_rlval result lvalue + _zzq_default default value (result returned when running on real CPU) + _zzq_request request code + _zzq_arg1..5 request params + + The other two macros are used to support function wrapping, and are + a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the + guest's NRADDR pseudo-register and whatever other information is + needed to safely run the call original from the wrapper: on + ppc64-linux, the R2 value at the divert point is also needed. This + information is abstracted into a user-visible type, OrigFn. + + VALGRIND_CALL_NOREDIR_* behaves the same as the following on the + guest, but guarantees that the branch instruction will not be + redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: + branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a + complete inline asm, since it needs to be combined with more magic + inline asm stuff to be useful. +*/ + +/* ----------------- x86-{linux,darwin,solaris} ---------------- */ + +#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ + || (defined(PLAT_x86_win32) && defined(__GNUC__)) \ + || defined(PLAT_x86_solaris) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "roll $3, %%edi ; roll $13, %%edi\n\t" \ + "roll $29, %%edi ; roll $19, %%edi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EDX = client_request ( %EAX ) */ \ + "xchgl %%ebx,%%ebx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EAX = guest_NRADDR */ \ + "xchgl %%ecx,%%ecx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_EAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%EAX */ \ + "xchgl %%edx,%%edx\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "xchgl %%edi,%%edi\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) + || PLAT_x86_solaris */ + +/* ------------------------- x86-Win32 ------------------------- */ + +#if defined(PLAT_x86_win32) && !defined(__GNUC__) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#if defined(_MSC_VER) + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + __asm rol edi, 3 __asm rol edi, 13 \ + __asm rol edi, 29 __asm rol edi, 19 + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \ + (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \ + (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \ + (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5)) + +static __inline uintptr_t +valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request, + uintptr_t _zzq_arg1, uintptr_t _zzq_arg2, + uintptr_t _zzq_arg3, uintptr_t _zzq_arg4, + uintptr_t _zzq_arg5) +{ + volatile uintptr_t _zzq_args[6]; + volatile unsigned int _zzq_result; + _zzq_args[0] = (uintptr_t)(_zzq_request); + _zzq_args[1] = (uintptr_t)(_zzq_arg1); + _zzq_args[2] = (uintptr_t)(_zzq_arg2); + _zzq_args[3] = (uintptr_t)(_zzq_arg3); + _zzq_args[4] = (uintptr_t)(_zzq_arg4); + _zzq_args[5] = (uintptr_t)(_zzq_arg5); + __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default + __SPECIAL_INSTRUCTION_PREAMBLE + /* %EDX = client_request ( %EAX ) */ + __asm xchg ebx,ebx + __asm mov _zzq_result, edx + } + return _zzq_result; +} + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EAX = guest_NRADDR */ \ + __asm xchg ecx,ecx \ + __asm mov __addr, eax \ + } \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_EAX ERROR + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ + __asm xchg edi,edi \ + } \ + } while (0) + +#else +#error Unsupported compiler. +#endif + +#endif /* PLAT_x86_win32 */ + +/* ----------------- amd64-{linux,darwin,solaris} --------------- */ + +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ + || defined(PLAT_amd64_solaris) \ + || (defined(PLAT_amd64_win64) && defined(__GNUC__)) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ + "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RDX = client_request ( %RAX ) */ \ + "xchgq %%rbx,%%rbx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RAX = guest_NRADDR */ \ + "xchgq %%rcx,%%rcx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_RAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%RAX */ \ + "xchgq %%rdx,%%rdx\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "xchgq %%rdi,%%rdi\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */ + +/* ------------------------- amd64-Win64 ------------------------- */ + +#if defined(PLAT_amd64_win64) && !defined(__GNUC__) + +#error Unsupported compiler. + +#endif /* PLAT_amd64_win64 */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \ + "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned int _zzq_args[6]; \ + unsigned int _zzq_result; \ + unsigned int* _zzq_ptr; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64be_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + unsigned long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned long int _zzq_args[6]; \ + unsigned long int _zzq_result; \ + unsigned long int* _zzq_ptr; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc64be_linux */ + +#if defined(PLAT_ppc64le_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + unsigned long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned long int _zzq_args[6]; \ + unsigned long int _zzq_result; \ + unsigned long int* _zzq_ptr; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R12 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc64le_linux */ + +/* ------------------------- arm-linux ------------------------- */ + +#if defined(PLAT_arm_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ + "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile("mov r3, %1\n\t" /*default*/ \ + "mov r4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* R3 = client_request ( R4 ) */ \ + "orr r10, r10, r10\n\t" \ + "mov %0, r3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "cc","memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* R3 = guest_NRADDR */ \ + "orr r11, r11, r11\n\t" \ + "mov %0, r3" \ + : "=r" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R4 */ \ + "orr r12, r12, r12\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "orr r9, r9, r9\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_arm_linux */ + +/* ------------------------ arm64-linux ------------------------- */ + +#if defined(PLAT_arm64_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \ + "ror x12, x12, #51 ; ror x12, x12, #61 \n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile("mov x3, %1\n\t" /*default*/ \ + "mov x4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* X3 = client_request ( X4 ) */ \ + "orr x10, x10, x10\n\t" \ + "mov %0, x3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" ((unsigned long int)(_zzq_default)), \ + "r" (&_zzq_args[0]) \ + : "cc","memory", "x3", "x4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* X3 = guest_NRADDR */ \ + "orr x11, x11, x11\n\t" \ + "mov %0, x3" \ + : "=r" (__addr) \ + : \ + : "cc", "memory", "x3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir X8 */ \ + "orr x12, x12, x12\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "orr x9, x9, x9\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_arm64_linux */ + +/* ------------------------ s390x-linux ------------------------ */ + +#if defined(PLAT_s390x_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + } + OrigFn; + +/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific + * code. This detection is implemented in platform specific toIR.c + * (e.g. VEX/priv/guest_s390_decoder.c). + */ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "lr 15,15\n\t" \ + "lr 1,1\n\t" \ + "lr 2,2\n\t" \ + "lr 3,3\n\t" + +#define __CLIENT_REQUEST_CODE "lr 2,2\n\t" +#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t" +#define __CALL_NO_REDIR_CODE "lr 4,4\n\t" +#define __VEX_INJECT_IR_CODE "lr 5,5\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile(/* r2 = args */ \ + "lgr 2,%1\n\t" \ + /* r3 = default */ \ + "lgr 3,%2\n\t" \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + __CLIENT_REQUEST_CODE \ + /* results = r3 */ \ + "lgr %0, 3\n\t" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "2", "3", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + __GET_NR_CONTEXT_CODE \ + "lgr %0, 3\n\t" \ + : "=a" (__addr) \ + : \ + : "cc", "3", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_R1 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + __CALL_NO_REDIR_CODE + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + __VEX_INJECT_IR_CODE); \ + } while (0) + +#endif /* PLAT_s390x_linux */ + +/* ------------------------- mips32-linux ---------------- */ + +#if defined(PLAT_mips32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +/* .word 0x342 + * .word 0x742 + * .word 0xC2 + * .word 0x4C2*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "srl $0, $0, 13\n\t" \ + "srl $0, $0, 29\n\t" \ + "srl $0, $0, 3\n\t" \ + "srl $0, $0, 19\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* T3 = client_request ( T4 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "$11", "$12", "memory"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %t9 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "$11" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%t9 */ \ + "or $15, $15, $15\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or $11, $11, $11\n\t" \ + ); \ + } while (0) + + +#endif /* PLAT_mips32_linux */ + +/* ------------------------- mips64-linux ---------------- */ + +#if defined(PLAT_mips64_linux) + +typedef + struct { + unsigned long nraddr; /* where's the code? */ + } + OrigFn; + +/* dsll $0,$0, 3 + * dsll $0,$0, 13 + * dsll $0,$0, 29 + * dsll $0,$0, 19*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \ + "dsll $0,$0,29 ; dsll $0,$0,19\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = client_request ( $12 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "$11", "$12", "memory"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "$11"); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir $25 */ \ + "or $15, $15, $15\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or $11, $11, $11\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_mips64_linux */ + +/* Insert assembly code for other platforms here... */ + +#endif /* NVALGRIND */ + + +/* ------------------------------------------------------------------ */ +/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ +/* ugly. It's the least-worst tradeoff I can think of. */ +/* ------------------------------------------------------------------ */ + +/* This section defines magic (a.k.a appalling-hack) macros for doing + guaranteed-no-redirection macros, so as to get from function + wrappers to the functions they are wrapping. The whole point is to + construct standard call sequences, but to do the call itself with a + special no-redirect call pseudo-instruction that the JIT + understands and handles specially. This section is long and + repetitious, and I can't see a way to make it shorter. + + The naming scheme is as follows: + + CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} + + 'W' stands for "word" and 'v' for "void". Hence there are + different macros for calling arity 0, 1, 2, 3, 4, etc, functions, + and for each, the possibility of returning a word-typed result, or + no result. +*/ + +/* Use these to write the name of your wrapper. NOTE: duplicates + VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts + the default behaviour equivalance class tag "0000" into the name. + See pub_tool_redir.h for details -- normally you don't need to + think about this, though. */ + +/* Use an extra level of macroisation so as to ensure the soname/fnname + args are fully macro-expanded before pasting them together. */ +#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd + +#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ + VG_CONCAT4(_vgw00000ZU_,soname,_,fnname) + +#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ + VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname) + +/* Use this macro from within a wrapper function to collect the + context (address and possibly other info) of the original function. + Once you have that you can then use it in one of the CALL_FN_ + macros. The type of the argument _lval is OrigFn. */ +#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) + +/* Also provide end-user facilities for function replacement, rather + than wrapping. A replacement function differs from a wrapper in + that it has no way to get hold of the original function being + called, and hence no way to call onwards to it. In a replacement + function, VALGRIND_GET_ORIG_FN always returns zero. */ + +#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \ + VG_CONCAT4(_vgr00000ZU_,soname,_,fnname) + +#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \ + VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname) + +/* Derivatives of the main macros below, for calling functions + returning void. */ + +#define CALL_FN_v_v(fnptr) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_v(_junk,fnptr); } while (0) + +#define CALL_FN_v_W(fnptr, arg1) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_W(_junk,fnptr,arg1); } while (0) + +#define CALL_FN_v_WW(fnptr, arg1,arg2) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) + +#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) + +#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) + +#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) + +#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) + +#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) + +/* ----------------- x86-{linux,darwin,solaris} ---------------- */ + +#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ + || defined(PLAT_x86_solaris) + +/* These regs are trashed by the hidden call. No need to mention eax + as gcc can already see that, plus causes gcc to bomb. */ +#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "movl %%esp,%%edi\n\t" \ + "andl $0xfffffff0,%%esp\n\t" +#define VALGRIND_RESTORE_STACK \ + "movl %%edi,%%esp\n\t" + +/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 48(%%eax)\n\t" \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */ + +/* ---------------- amd64-{linux,darwin,solaris} --------------- */ + +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ + || defined(PLAT_amd64_solaris) + +/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ + "rdi", "r8", "r9", "r10", "r11" + +/* This is all pretty complex. It's so as to make stack unwinding + work reliably. See bug 243270. The basic problem is the sub and + add of 128 of %rsp in all of the following macros. If gcc believes + the CFA is in %rsp, then unwinding may fail, because what's at the + CFA is not what gcc "expected" when it constructs the CFIs for the + places where the macros are instantiated. + + But we can't just add a CFI annotation to increase the CFA offset + by 128, to match the sub of 128 from %rsp, because we don't know + whether gcc has chosen %rsp as the CFA at that point, or whether it + has chosen some other register (eg, %rbp). In the latter case, + adding a CFI annotation to change the CFA offset is simply wrong. + + So the solution is to get hold of the CFA using + __builtin_dwarf_cfa(), put it in a known register, and add a + CFI annotation to say what the register is. We choose %rbp for + this (perhaps perversely), because: + + (1) %rbp is already subject to unwinding. If a new register was + chosen then the unwinder would have to unwind it in all stack + traces, which is expensive, and + + (2) %rbp is already subject to precise exception updates in the + JIT. If a new register was chosen, we'd have to have precise + exceptions for it too, which reduces performance of the + generated code. + + However .. one extra complication. We can't just whack the result + of __builtin_dwarf_cfa() into %rbp and then add %rbp to the + list of trashed registers at the end of the inline assembly + fragments; gcc won't allow %rbp to appear in that list. Hence + instead we need to stash %rbp in %r15 for the duration of the asm, + and say that %r15 is trashed instead. gcc seems happy to go with + that. + + Oh .. and this all needs to be conditionalised so that it is + unchanged from before this commit, when compiled with older gccs + that don't support __builtin_dwarf_cfa. Furthermore, since + this header file is freestanding, it has to be independent of + config.h, and so the following conditionalisation cannot depend on + configure time checks. + + Although it's not clear from + 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', + this expression excludes Darwin. + .cfi directives in Darwin assembly appear to be completely + different and I haven't investigated how they work. + + For even more entertainment value, note we have to use the + completely undocumented __builtin_dwarf_cfa(), which appears to + really compute the CFA, whereas __builtin_frame_address(0) claims + to but actually doesn't. See + https://bugs.kde.org/show_bug.cgi?id=243270#c47 +*/ +#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) +# define __FRAME_POINTER \ + ,"r"(__builtin_dwarf_cfa()) +# define VALGRIND_CFI_PROLOGUE \ + "movq %%rbp, %%r15\n\t" \ + "movq %2, %%rbp\n\t" \ + ".cfi_remember_state\n\t" \ + ".cfi_def_cfa rbp, 0\n\t" +# define VALGRIND_CFI_EPILOGUE \ + "movq %%r15, %%rbp\n\t" \ + ".cfi_restore_state\n\t" +#else +# define __FRAME_POINTER +# define VALGRIND_CFI_PROLOGUE +# define VALGRIND_CFI_EPILOGUE +#endif + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "movq %%rsp,%%r14\n\t" \ + "andq $0xfffffffffffffff0,%%rsp\n\t" +#define VALGRIND_RESTORE_STACK \ + "movq %%r14,%%rsp\n\t" + +/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned + long) == 8. */ + +/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ + macros. In order not to trash the stack redzone, we need to drop + %rsp by 128 before the hidden call, and restore afterwards. The + nastyness is that it is only by luck that the stack still appears + to be unwindable during the hidden call - since then the behaviour + of any routine using this macro does not match what the CFI data + says. Sigh. + + Why is this important? Imagine that a wrapper has a stack + allocated local, and passes to the hidden call, a pointer to it. + Because gcc does not know about the hidden call, it may allocate + that local in the redzone. Unfortunately the hidden call may then + trash it before it comes to use it. So we must step clear of the + redzone, for the duration of the hidden call, to make it safe. + + Probably the same problem afflicts the other redzone-style ABIs too + (ppc64-linux); but for those, the stack is + self describing (none of this CFI nonsense) so at least messing + with the stack pointer doesn't give a danger of non-unwindable + stack. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 96(%%rax)\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +/* This is useful for finding out about the on-stack stuff: + + extern int f9 ( int,int,int,int,int,int,int,int,int ); + extern int f10 ( int,int,int,int,int,int,int,int,int,int ); + extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); + extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); + + int g9 ( void ) { + return f9(11,22,33,44,55,66,77,88,99); + } + int g10 ( void ) { + return f10(11,22,33,44,55,66,77,88,99,110); + } + int g11 ( void ) { + return f11(11,22,33,44,55,66,77,88,99,110,121); + } + int g12 ( void ) { + return f12(11,22,33,44,55,66,77,88,99,110,121,132); + } +*/ + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rlwinm 1,1,0,0,27\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc32-linux, + sizeof(unsigned long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + _argvec[12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg12 */ \ + "lwz 3,48(11)\n\t" \ + "stw 3,20(1)\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64be_linux) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rldicr 1,1,0,59\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg12 */ \ + "ld 3,96(11)\n\t" \ + "std 3,136(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64be_linux */ + +/* ------------------------- ppc64le-linux ----------------------- */ +#if defined(PLAT_ppc64le_linux) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rldicr 1,1,0,59\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg11 */ \ + "ld 3,88(12)\n\t" \ + "std 3,112(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg12 */ \ + "ld 3,96(12)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(12)\n\t" \ + "std 3,112(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64le_linux */ + +/* ------------------------- arm-linux ------------------------- */ + +#if defined(PLAT_arm_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +/* This is a bit tricky. We store the original stack pointer in r10 + as it is callee-saves. gcc doesn't allow the use of r11 for some + reason. Also, we can't directly "bic" the stack pointer in thumb + mode since r13 isn't an allowed register number in that context. + So use r4 as a temporary, since that is about to get trashed + anyway, just after each use of this macro. Side effect is we need + to be very careful about any future changes, since + VALGRIND_ALIGN_STACK simply assumes r4 is usable. */ +#define VALGRIND_ALIGN_STACK \ + "mov r10, sp\n\t" \ + "mov r4, sp\n\t" \ + "bic r4, r4, #7\n\t" \ + "mov sp, r4\n\t" +#define VALGRIND_RESTORE_STACK \ + "mov sp, r10\n\t" + +/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "push {r0} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "push {r0, r1} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "push {r0, r1, r2} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "push {r0, r1, r2, r3} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #40] \n\t" \ + "push {r0} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #40] \n\t" \ + "ldr r1, [%1, #44] \n\t" \ + "push {r0, r1} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #40] \n\t" \ + "ldr r1, [%1, #44] \n\t" \ + "ldr r2, [%1, #48] \n\t" \ + "push {r0, r1, r2} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_arm_linux */ + +/* ------------------------ arm64-linux ------------------------ */ + +#if defined(PLAT_arm64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \ + "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \ + "x18", "x19", "x20", "x30", \ + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \ + "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \ + "v26", "v27", "v28", "v29", "v30", "v31" + +/* x21 is callee-saved, so we can use it to save and restore SP around + the hidden call. */ +#define VALGRIND_ALIGN_STACK \ + "mov x21, sp\n\t" \ + "bic sp, x21, #15\n\t" +#define VALGRIND_RESTORE_STACK \ + "mov sp, x21\n\t" + +/* These CALL_FN_ macros assume that on arm64-linux, + sizeof(unsigned long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x20 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x20 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x30 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1, #88] \n\t" \ + "str x8, [sp, #16] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11, \ + arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x30 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1, #88] \n\t" \ + "str x8, [sp, #16] \n\t" \ + "ldr x8, [%1, #96] \n\t" \ + "str x8, [sp, #24] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_arm64_linux */ + +/* ------------------------- s390x-linux ------------------------- */ + +#if defined(PLAT_s390x_linux) + +/* Similar workaround as amd64 (see above), but we use r11 as frame + pointer and save the old r11 in r7. r11 might be used for + argvec, therefore we copy argvec in r1 since r1 is clobbered + after the call anyway. */ +#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) +# define __FRAME_POINTER \ + ,"d"(__builtin_dwarf_cfa()) +# define VALGRIND_CFI_PROLOGUE \ + ".cfi_remember_state\n\t" \ + "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \ + "lgr 7,11\n\t" \ + "lgr 11,%2\n\t" \ + ".cfi_def_cfa r11, 0\n\t" +# define VALGRIND_CFI_EPILOGUE \ + "lgr 11, 7\n\t" \ + ".cfi_restore_state\n\t" +#else +# define __FRAME_POINTER +# define VALGRIND_CFI_PROLOGUE \ + "lgr 1,%1\n\t" +# define VALGRIND_CFI_EPILOGUE +#endif + +/* Nb: On s390 the stack pointer is properly aligned *at all times* + according to the s390 GCC maintainer. (The ABI specification is not + precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and + VALGRIND_RESTORE_STACK are not defined here. */ + +/* These regs are trashed by the hidden call. Note that we overwrite + r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the + function a proper return address. All others are ABI defined call + clobbers. */ +#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \ + "f0","f1","f2","f3","f4","f5","f6","f7" + +/* Nb: Although r11 is modified in the asm snippets below (inside + VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for + two reasons: + (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not + modified + (2) GCC will complain that r11 cannot appear inside a clobber section, + when compiled with -O -fno-omit-frame-pointer + */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 1, 0(1)\n\t" /* target->r1 */ \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +/* The call abi has the arguments in r2-r6 and stack */ +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-168\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,168\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-176\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,176\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-184\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,184\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-192\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,192\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-200\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,200\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10, arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-208\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "mvc 200(8,15), 88(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,208\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + _argvec[12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-216\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "mvc 200(8,15), 88(1)\n\t" \ + "mvc 208(8,15), 96(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,216\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + + +#endif /* PLAT_s390x_linux */ + +/* ------------------------- mips32-linux ----------------------- */ + +#if defined(PLAT_mips32_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ +"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ +"$25", "$31" + +/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16\n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" /* arg1*/ \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 24\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 24 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "nop\n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 56\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 48(%1) \n\t" \ + "sw $4, 44($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 56 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips32_linux */ + +/* ------------------------- mips64-linux ------------------------- */ + +#if defined(PLAT_mips64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ +"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ +"$25", "$31" + +/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" /* arg1*/ \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "dsubu $29, $29, 8\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 8\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "dsubu $29, $29, 16\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 16\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "dsubu $29, $29, 24\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 24\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "dsubu $29, $29, 32\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 96(%1)\n\t" \ + "sd $4, 24($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 32\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips64_linux */ + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ +/* */ +/* ------------------------------------------------------------------ */ + +/* Some request codes. There are many more of these, but most are not + exposed to end-user view. These are the public ones, all of the + form 0x1000 + small_number. + + Core ones are in the range 0x00000000--0x0000ffff. The non-public + ones start at 0x2000. +*/ + +/* These macros are used by tools -- they must be public, but don't + embed them into other programs. */ +#define VG_USERREQ_TOOL_BASE(a,b) \ + ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) +#define VG_IS_TOOL_USERREQ(a, b, v) \ + (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) + +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! + This enum comprises an ABI exported by Valgrind to programs + which use client requests. DO NOT CHANGE THE NUMERIC VALUES OF THESE + ENTRIES, NOR DELETE ANY -- add new ones at the end of the most + relevant group. */ +typedef + enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, + VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, + + /* These allow any function to be called from the simulated + CPU but run on the real CPU. Nb: the first arg passed to + the function is always the ThreadId of the running + thread! So CLIENT_CALL0 actually requires a 1 arg + function, etc. */ + VG_USERREQ__CLIENT_CALL0 = 0x1101, + VG_USERREQ__CLIENT_CALL1 = 0x1102, + VG_USERREQ__CLIENT_CALL2 = 0x1103, + VG_USERREQ__CLIENT_CALL3 = 0x1104, + + /* Can be useful in regression testing suites -- eg. can + send Valgrind's output to /dev/null and still count + errors. */ + VG_USERREQ__COUNT_ERRORS = 0x1201, + + /* Allows the client program and/or gdbserver to execute a monitor + command. */ + VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202, + + /* These are useful and can be interpreted by any tool that + tracks malloc() et al, by using vg_replace_malloc.c. */ + VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, + VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b, + VG_USERREQ__FREELIKE_BLOCK = 0x1302, + /* Memory pool support. */ + VG_USERREQ__CREATE_MEMPOOL = 0x1303, + VG_USERREQ__DESTROY_MEMPOOL = 0x1304, + VG_USERREQ__MEMPOOL_ALLOC = 0x1305, + VG_USERREQ__MEMPOOL_FREE = 0x1306, + VG_USERREQ__MEMPOOL_TRIM = 0x1307, + VG_USERREQ__MOVE_MEMPOOL = 0x1308, + VG_USERREQ__MEMPOOL_CHANGE = 0x1309, + VG_USERREQ__MEMPOOL_EXISTS = 0x130a, + + /* Allow printfs to valgrind log. */ + /* The first two pass the va_list argument by value, which + assumes it is the same size as or smaller than a UWord, + which generally isn't the case. Hence are deprecated. + The second two pass the vargs by reference and so are + immune to this problem. */ + /* both :: char* fmt, va_list vargs (DEPRECATED) */ + VG_USERREQ__PRINTF = 0x1401, + VG_USERREQ__PRINTF_BACKTRACE = 0x1402, + /* both :: char* fmt, va_list* vargs */ + VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, + + /* Stack support. */ + VG_USERREQ__STACK_REGISTER = 0x1501, + VG_USERREQ__STACK_DEREGISTER = 0x1502, + VG_USERREQ__STACK_CHANGE = 0x1503, + + /* Wine support */ + VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, + + /* Querying of debug info. */ + VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701, + + /* Disable/enable error reporting level. Takes a single + Word arg which is the delta to this thread's error + disablement indicator. Hence 1 disables or further + disables errors, and -1 moves back towards enablement. + Other values are not allowed. */ + VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801, + + /* Some requests used for Valgrind internal, such as + self-test or self-hosting. */ + /* Initialise IR injection */ + VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901, + /* Used by Inner Valgrind to inform Outer Valgrind where to + find the list of inner guest threads */ + VG_USERREQ__INNER_THREADS = 0x1902 + } Vg_ClientRequest; + +#if !defined(__GNUC__) +# define __extension__ /* */ +#endif + + +/* Returns the number of Valgrinds this code is running under. That + is, 0 if running natively, 1 if running under Valgrind, 2 if + running under Valgrind which is running under another Valgrind, + etc. */ +#define RUNNING_ON_VALGRIND \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ + VG_USERREQ__RUNNING_ON_VALGRIND, \ + 0, 0, 0, 0, 0) \ + + +/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + + _qzz_len - 1]. Useful if you are debugging a JITter or some such, + since it provides a way to make sure valgrind will retranslate the + invalidated area. Returns no value. */ +#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \ + _qzz_addr, _qzz_len, 0, 0, 0) + +#define VALGRIND_INNER_THREADS(_qzz_addr) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS, \ + _qzz_addr, 0, 0, 0, 0) + + +/* These requests are for getting Valgrind itself to print something. + Possibly with a backtrace. This is a really ugly hack. The return value + is the number of characters printed, excluding the "**** " part at the + start and the backtrace (if present). */ + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) +/* Modern GCC will optimize the static routine out if unused, + and unused attribute will shut down warnings about it. */ +static int VALGRIND_PRINTF(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +#endif +static int +#if defined(_MSC_VER) +__inline +#endif +VALGRIND_PRINTF(const char *format, ...) +{ +#if defined(NVALGRIND) + (void)format; + return 0; +#else /* NVALGRIND */ +#if defined(_MSC_VER) || defined(__MINGW64__) + uintptr_t _qzz_res; +#else + unsigned long _qzz_res; +#endif + va_list vargs; + va_start(vargs, format); +#if defined(_MSC_VER) || defined(__MINGW64__) + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_VALIST_BY_REF, + (uintptr_t)format, + (uintptr_t)&vargs, + 0, 0, 0); +#else + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_VALIST_BY_REF, + (unsigned long)format, + (unsigned long)&vargs, + 0, 0, 0); +#endif + va_end(vargs); + return (int)_qzz_res; +#endif /* NVALGRIND */ +} + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) +static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +#endif +static int +#if defined(_MSC_VER) +__inline +#endif +VALGRIND_PRINTF_BACKTRACE(const char *format, ...) +{ +#if defined(NVALGRIND) + (void)format; + return 0; +#else /* NVALGRIND */ +#if defined(_MSC_VER) || defined(__MINGW64__) + uintptr_t _qzz_res; +#else + unsigned long _qzz_res; +#endif + va_list vargs; + va_start(vargs, format); +#if defined(_MSC_VER) || defined(__MINGW64__) + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, + (uintptr_t)format, + (uintptr_t)&vargs, + 0, 0, 0); +#else + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, + (unsigned long)format, + (unsigned long)&vargs, + 0, 0, 0); +#endif + va_end(vargs); + return (int)_qzz_res; +#endif /* NVALGRIND */ +} + + +/* These requests allow control to move from the simulated CPU to the + real CPU, calling an arbitrary function. + + Note that the current ThreadId is inserted as the first argument. + So this call: + + VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) + + requires f to have this signature: + + Word f(Word tid, Word arg1, Word arg2) + + where "Word" is a word-sized type. + + Note that these client requests are not entirely reliable. For example, + if you call a function with them that subsequently calls printf(), + there's a high chance Valgrind will crash. Generally, your prospects of + these working are made higher if the called function does not refer to + any global variables, and does not refer to any libc or other functions + (printf et al). Any kind of entanglement with libc or dynamic linking is + likely to have a bad outcome, for tricky reasons which we've grappled + with a lot in the past. +*/ +#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL0, \ + _qyy_fn, \ + 0, 0, 0, 0) + +#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL1, \ + _qyy_fn, \ + _qyy_arg1, 0, 0, 0) + +#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL2, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, 0, 0) + +#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL3, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, \ + _qyy_arg3, 0) + + +/* Counts the number of errors that have been recorded by a tool. Nb: + the tool must record the errors with VG_(maybe_record_error)() or + VG_(unique_error)() for them to be counted. */ +#define VALGRIND_COUNT_ERRORS \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + 0 /* default return */, \ + VG_USERREQ__COUNT_ERRORS, \ + 0, 0, 0, 0, 0) + +/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing + when heap blocks are allocated in order to give accurate results. This + happens automatically for the standard allocator functions such as + malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, + delete[], etc. + + But if your program uses a custom allocator, this doesn't automatically + happen, and Valgrind will not do as well. For example, if you allocate + superblocks with mmap() and then allocates chunks of the superblocks, all + Valgrind's observations will be at the mmap() level and it won't know that + the chunks should be considered separate entities. In Memcheck's case, + that means you probably won't get heap block overrun detection (because + there won't be redzones marked as unaddressable) and you definitely won't + get any leak detection. + + The following client requests allow a custom allocator to be annotated so + that it can be handled accurately by Valgrind. + + VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated + by a malloc()-like function. For Memcheck (an illustrative case), this + does two things: + + - It records that the block has been allocated. This means any addresses + within the block mentioned in error messages will be + identified as belonging to the block. It also means that if the block + isn't freed it will be detected by the leak checker. + + - It marks the block as being addressable and undefined (if 'is_zeroed' is + not set), or addressable and defined (if 'is_zeroed' is set). This + controls how accesses to the block by the program are handled. + + 'addr' is the start of the usable block (ie. after any + redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator + can apply redzones -- these are blocks of padding at the start and end of + each block. Adding redzones is recommended as it makes it much more likely + Valgrind will spot block overruns. `is_zeroed' indicates if the memory is + zeroed (or filled with another predictable value), as is the case for + calloc(). + + VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a + heap block -- that will be used by the client program -- is allocated. + It's best to put it at the outermost level of the allocator if possible; + for example, if you have a function my_alloc() which calls + internal_alloc(), and the client request is put inside internal_alloc(), + stack traces relating to the heap block will contain entries for both + my_alloc() and internal_alloc(), which is probably not what you want. + + For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out + custom blocks from within a heap block, B, that has been allocated with + malloc/calloc/new/etc, then block B will be *ignored* during leak-checking + -- the custom blocks will take precedence. + + VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For + Memcheck, it does two things: + + - It records that the block has been deallocated. This assumes that the + block was annotated as having been allocated via + VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. + + - It marks the block as being unaddressable. + + VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a + heap block is deallocated. + + VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For + Memcheck, it does four things: + + - It records that the size of a block has been changed. This assumes that + the block was annotated as having been allocated via + VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. + + - If the block shrunk, it marks the freed memory as being unaddressable. + + - If the block grew, it marks the new area as undefined and defines a red + zone past the end of the new block. + + - The V-bits of the overlap between the old and the new block are preserved. + + VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block + and before deallocation of the old block. + + In many cases, these three client requests will not be enough to get your + allocator working well with Memcheck. More specifically, if your allocator + writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call + will be necessary to mark the memory as addressable just before the zeroing + occurs, otherwise you'll get a lot of invalid write errors. For example, + you'll need to do this if your allocator recycles freed blocks, but it + zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). + Alternatively, if your allocator reuses freed blocks for allocator-internal + data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. + + Really, what's happening is a blurring of the lines between the client + program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the + memory should be considered unaddressable to the client program, but the + allocator knows more than the rest of the client program and so may be able + to safely access it. Extra client requests are necessary for Valgrind to + understand the distinction between the allocator and the rest of the + program. + + Ignored if addr == 0. +*/ +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \ + addr, sizeB, rzB, is_zeroed, 0) + +/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. + Ignored if addr == 0. +*/ +#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \ + addr, oldSizeB, newSizeB, rzB, 0) + +/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. + Ignored if addr == 0. +*/ +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \ + addr, rzB, 0, 0, 0) + +/* Create a memory pool. */ +#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ + pool, rzB, is_zeroed, 0, 0) + +/* Create a memory pool with some flags specifying extended behaviour. + When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL. + + The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory + associated with the pool using VALGRIND_MEMPOOL_ALLOC will be used + by the application as superblocks to dole out MALLOC_LIKE blocks using + VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels" + pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC. + The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK. + Note that the association between the pool and the second level blocks + is implicit : second level blocks will be located inside first level + blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag + for such 2 levels pools, as otherwise valgrind will detect overlapping + memory blocks, and will abort execution (e.g. during leak search). + + Such a meta pool can also be marked as an 'auto free' pool using the flag + VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the + VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE + will automatically free the second level blocks that are contained + inside the first level block freed with VALGRIND_MEMPOOL_FREE. + In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls + to VALGRIND_FREELIKE_BLOCK for all the second level blocks included + in the first level block. + Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag + without the VALGRIND_MEMPOOL_METAPOOL flag. +*/ +#define VALGRIND_MEMPOOL_AUTO_FREE 1 +#define VALGRIND_MEMPOOL_METAPOOL 2 +#define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ + pool, rzB, is_zeroed, flags, 0) + +/* Destroy a memory pool. */ +#define VALGRIND_DESTROY_MEMPOOL(pool) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \ + pool, 0, 0, 0, 0) + +/* Associate a piece of memory with a memory pool. */ +#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \ + pool, addr, size, 0, 0) + +/* Disassociate a piece of memory from a memory pool. */ +#define VALGRIND_MEMPOOL_FREE(pool, addr) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \ + pool, addr, 0, 0, 0) + +/* Disassociate any pieces outside a particular range. */ +#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \ + pool, addr, size, 0, 0) + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \ + poolA, poolB, 0, 0, 0) + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \ + pool, addrA, addrB, size, 0) + +/* Return 1 if a mempool exists, else 0. */ +#define VALGRIND_MEMPOOL_EXISTS(pool) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__MEMPOOL_EXISTS, \ + pool, 0, 0, 0, 0) + +/* Mark a piece of memory as being a stack. Returns a stack id. + start is the lowest addressable stack byte, end is the highest + addressable stack byte. */ +#define VALGRIND_STACK_REGISTER(start, end) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__STACK_REGISTER, \ + start, end, 0, 0, 0) + +/* Unmark the piece of memory associated with a stack id as being a + stack. */ +#define VALGRIND_STACK_DEREGISTER(id) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \ + id, 0, 0, 0, 0) + +/* Change the start and end address of the stack id. + start is the new lowest addressable stack byte, end is the new highest + addressable stack byte. */ +#define VALGRIND_STACK_CHANGE(id, start, end) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \ + id, start, end, 0, 0) + +/* Load PDB debug info for Wine PE image_map. */ +#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \ + fd, ptr, total_size, delta, 0) + +/* Map a code address to a source file name and line number. buf64 + must point to a 64-byte buffer in the caller's address space. The + result will be dumped in there and is guaranteed to be zero + terminated. If no info is found, the first byte is set to zero. */ +#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__MAP_IP_TO_SRCLOC, \ + addr, buf64, 0, 0, 0) + +/* Disable error reporting for this thread. Behaves in a stack like + way, so you can safely call this multiple times provided that + VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times + to re-enable reporting. The first call of this macro disables + reporting. Subsequent calls have no effect except to increase the + number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable + reporting. Child threads do not inherit this setting from their + parents -- they are always created with reporting enabled. */ +#define VALGRIND_DISABLE_ERROR_REPORTING \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ + 1, 0, 0, 0, 0) + +/* Re-enable error reporting, as per comments on + VALGRIND_DISABLE_ERROR_REPORTING. */ +#define VALGRIND_ENABLE_ERROR_REPORTING \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ + -1, 0, 0, 0, 0) + +/* Execute a monitor command from the client program. + If a connection is opened with GDB, the output will be sent + according to the output mode set for vgdb. + If no connection is opened, output will go to the log output. + Returns 1 if command not recognised, 0 otherwise. */ +#define VALGRIND_MONITOR_COMMAND(command) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \ + command, 0, 0, 0, 0) + + +#undef PLAT_x86_darwin +#undef PLAT_amd64_darwin +#undef PLAT_x86_win32 +#undef PLAT_amd64_win64 +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64be_linux +#undef PLAT_ppc64le_linux +#undef PLAT_arm_linux +#undef PLAT_s390x_linux +#undef PLAT_mips32_linux +#undef PLAT_mips64_linux +#undef PLAT_x86_solaris +#undef PLAT_amd64_solaris + +#endif /* __VALGRIND_H */ diff -Nru flatpak-0.11.7/completion/flatpak flatpak-0.11.8.3/completion/flatpak --- flatpak-0.11.7/completion/flatpak 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/completion/flatpak 2018-05-30 13:58:57.000000000 +0100 @@ -13,9 +13,9 @@ if [[ "${RES[$i]}" = "__FLATPAK_FILE" ]]; then declare -a COMPGEN_OPTS=('-f') elif [[ "${RES[$i]}" = "__FLATPAK_BUNDLE_FILE" ]]; then - declare -a COMPGEN_OPTS=('-f' '-G' '*.flatpak') + declare -a COMPGEN_OPTS=('-f' '-X' '!*.flatpak') elif [[ "${RES[$i]}" = "__FLATPAK_BUNDLE_OR_REF_FILE" ]]; then - declare -a COMPGEN_OPTS=('-f' '-G' '*.flatpak@(|ref)') + declare -a COMPGEN_OPTS=('-f' '-X' '!*.flatpak@(|ref)') elif [[ "${RES[$i]}" = "__FLATPAK_DIR" ]]; then declare -a COMPGEN_OPTS=('-d') else diff -Nru flatpak-0.11.7/completion/_flatpak flatpak-0.11.8.3/completion/_flatpak --- flatpak-0.11.7/completion/_flatpak 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/completion/_flatpak 2018-05-30 13:58:57.000000000 +0100 @@ -0,0 +1,27 @@ +#compdef flatpak + +emulate -L zsh + +local index +(( index = ${(c)#words[0,CURRENT]} + $#PREFIX + 1 )) + + +local resp=($(flatpak complete "$words" $index "$words[CURRENT]")) + +_description options opt_expl option +_description arguments arg_expl argument + +local match +for match in $resp; do + case $match in + __FLATPAK_FILE) _files;; + __FLATPAK_BUNDLE_FILE) _path_files -g '*.flatpak';; + __FLATPAK_BUNDLE_OR_REF_FILE) _path_files -g '*.flatpak(|ref)';; + __FLATPAK_DIR) _path_files -/;; + -*=) compadd $opt_expl[@] -S "" -- $match;; + -*) compadd $opt_expl[@] -- $match;; + *) compadd $arg_expl[@] $match;; + esac +done + +# vim: ft=zsh diff -Nru flatpak-0.11.7/configure flatpak-0.11.8.3/configure --- flatpak-0.11.7/configure 2018-05-03 07:26:16.000000000 +0100 +++ flatpak-0.11.8.3/configure 2018-06-13 11:39:41.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Flatpak 0.11.7. +# Generated by GNU Autoconf 2.69 for Flatpak 0.11.8.3. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='Flatpak' PACKAGE_TARNAME='flatpak' -PACKAGE_VERSION='0.11.7' -PACKAGE_STRING='Flatpak 0.11.7' +PACKAGE_VERSION='0.11.8.3' +PACKAGE_STRING='Flatpak 0.11.8.3' PACKAGE_BUGREPORT='https://github.com/flatpak/flatpak/issues' PACKAGE_URL='http://flatpak.org/' @@ -694,6 +694,8 @@ SYSTEM_INSTALL_DIR ENABLE_P2P_FALSE ENABLE_P2P_TRUE +OSTREE_P2P_REQ_LIBS +OSTREE_P2P_REQ_CFLAGS SUDO_BIN PRIV_MODE_SETUID_FALSE PRIV_MODE_SETUID_TRUE @@ -920,7 +922,6 @@ enable_seccomp with_priv_mode enable_sudo -enable_p2p with_system_install_dir enable_documentation with_xml_catalog @@ -970,6 +971,8 @@ APPSTREAM_GLIB_LIBS LIBSECCOMP_CFLAGS LIBSECCOMP_LIBS +OSTREE_P2P_REQ_CFLAGS +OSTREE_P2P_REQ_LIBS GTKDOC_DEPS_CFLAGS GTKDOC_DEPS_LIBS XMLTO @@ -1514,7 +1517,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Flatpak 0.11.7 to adapt to many kinds of systems. +\`configure' configures Flatpak 0.11.8.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1584,7 +1587,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Flatpak 0.11.7:";; + short | recursive ) echo "Configuration of Flatpak 0.11.8.3:";; esac cat <<\_ACEOF @@ -1621,7 +1624,6 @@ --disable-seccomp Disable seccomp --enable-sudo Use sudo to set setuid flags on binaries during install (only needed if userns disabled) - --enable-p2p Enable unstable peer to peer support [default=no] --enable-documentation Build documentation --enable-introspection=[no/auto/yes] Enable introspection for this build @@ -1740,6 +1742,10 @@ C compiler flags for LIBSECCOMP, overriding pkg-config LIBSECCOMP_LIBS linker flags for LIBSECCOMP, overriding pkg-config + OSTREE_P2P_REQ_CFLAGS + C compiler flags for OSTREE_P2P_REQ, overriding pkg-config + OSTREE_P2P_REQ_LIBS + linker flags for OSTREE_P2P_REQ, overriding pkg-config GTKDOC_DEPS_CFLAGS C compiler flags for GTKDOC_DEPS, overriding pkg-config GTKDOC_DEPS_LIBS @@ -1814,7 +1820,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Flatpak configure 0.11.7 +Flatpak configure 0.11.8.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2229,7 +2235,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Flatpak $as_me 0.11.7, which was +It was created by Flatpak $as_me 0.11.8.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2580,8 +2586,8 @@ GLIB_REQS=2.44 -SYSTEM_BWRAP_REQS=0.1.8 -OSTREE_REQS=2017.14 +SYSTEM_BWRAP_REQS=0.2.1 +OSTREE_REQS=2017.15 OSTREE_P2P_REQS=2018.2 ac_aux_dir= @@ -4754,6 +4760,298 @@ + case $ac_cv_prog_cc_stdc in #( + no) : + ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 +else + ac_cv_prog_cc_stdc=no +fi + +fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 +$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } + if ${ac_cv_prog_cc_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +fi + + case $ac_cv_prog_cc_stdc in #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; #( + '') : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 +$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; +esac + case `pwd` in @@ -12977,7 +13275,7 @@ # Define the identity of the package. PACKAGE='flatpak' - VERSION='0.11.7' + VERSION='0.11.8.3' # Some tools Automake needs. @@ -17558,25 +17856,17 @@ -# Do we enable building peer to peer support using libostree’s experimental (non-stable) API? -# If so, OSTREE_ENABLE_EXPERIMENTAL_API needs to be #defined before ostree.h is -# included. -# Check whether --enable-p2p was given. -if test "${enable_p2p+set}" = set; then : - enableval=$enable_p2p; -else - enable_p2p=no -fi - -if test x$enable_p2p = xyes; then : - +# Decide whether to build with peer to peer support. This requires API in +# libostree which before 2018.6 was experimental. +#FIXME: Clean up when flatpak depends on 2018.6 +enable_p2p=no pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OSTREE" >&5 -$as_echo_n "checking for OSTREE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OSTREE_P2P_REQ" >&5 +$as_echo_n "checking for OSTREE_P2P_REQ... " >&6; } -if test -n "$OSTREE_CFLAGS"; then - pkg_cv_OSTREE_CFLAGS="$OSTREE_CFLAGS" +if test -n "$OSTREE_P2P_REQ_CFLAGS"; then + pkg_cv_OSTREE_P2P_REQ_CFLAGS="$OSTREE_P2P_REQ_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ostree-1 >= \$OSTREE_P2P_REQS\""; } >&5 @@ -17584,7 +17874,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OSTREE_CFLAGS=`$PKG_CONFIG --cflags "ostree-1 >= $OSTREE_P2P_REQS" 2>/dev/null` + pkg_cv_OSTREE_P2P_REQ_CFLAGS=`$PKG_CONFIG --cflags "ostree-1 >= $OSTREE_P2P_REQS" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -17592,8 +17882,8 @@ else pkg_failed=untried fi -if test -n "$OSTREE_LIBS"; then - pkg_cv_OSTREE_LIBS="$OSTREE_LIBS" +if test -n "$OSTREE_P2P_REQ_LIBS"; then + pkg_cv_OSTREE_P2P_REQ_LIBS="$OSTREE_P2P_REQ_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ostree-1 >= \$OSTREE_P2P_REQS\""; } >&5 @@ -17601,7 +17891,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OSTREE_LIBS=`$PKG_CONFIG --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>/dev/null` + pkg_cv_OSTREE_P2P_REQ_LIBS=`$PKG_CONFIG --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -17622,64 +17912,55 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OSTREE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>&1` + OSTREE_P2P_REQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>&1` else - OSTREE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>&1` + OSTREE_P2P_REQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ostree-1 >= $OSTREE_P2P_REQS" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$OSTREE_PKG_ERRORS" >&5 + echo "$OSTREE_P2P_REQ_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (ostree-1 >= $OSTREE_P2P_REQS) were not met: - -$OSTREE_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -Alternatively, you may set the environment variables OSTREE_CFLAGS -and OSTREE_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details." "$LINENO" 5 + : elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -Alternatively, you may set the environment variables OSTREE_CFLAGS -and OSTREE_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details. - -To get pkg-config, see . -See \`config.log' for more details" "$LINENO" 5; } + : else - OSTREE_CFLAGS=$pkg_cv_OSTREE_CFLAGS - OSTREE_LIBS=$pkg_cv_OSTREE_LIBS + OSTREE_P2P_REQ_CFLAGS=$pkg_cv_OSTREE_P2P_REQ_CFLAGS + OSTREE_P2P_REQ_LIBS=$pkg_cv_OSTREE_P2P_REQ_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } -fi ostree_features=$($PKG_CONFIG --variable=features ostree-1) case "$ostree_features" in #( *experimental*) : have_ostree_experimental=yes ;; #( + *p2p*) : + have_ostree_p2p=yes ;; #( *) : ;; esac - if test "x$have_ostree_experimental" != "xyes"; then : - as_fn_error $? "Experimental API not found in ostree-1, which is needed for --enable-p2p. OSTree must be compiled with --enable-experimental-api." "$LINENO" 5 -fi + if test "x$have_ostree_experimental" != "xyes" && test "x$have_ostree_p2p" != "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Experimental/P2P API not found in ostree-1, so flatpak will be compiled without P2P support. OSTree < 2018.6 must be compiled with --enable-experimental-api." >&5 +$as_echo "$as_me: WARNING: Experimental/P2P API not found in ostree-1, so flatpak will be compiled without P2P support. OSTree < 2018.6 must be compiled with --enable-experimental-api." >&2;} -$as_echo "#define OSTREE_ENABLE_EXPERIMENTAL_API 1" >>confdefs.h +else + enable_p2p=yes $as_echo "#define FLATPAK_ENABLE_P2P 1" >>confdefs.h + if test "x$have_ostree_experimental" == "xyes"; then : + + +$as_echo "#define OSTREE_ENABLE_EXPERIMENTAL_API 1" >>confdefs.h + + +fi + +fi fi if test x$enable_p2p = xyes; then @@ -18550,10 +18831,10 @@ FLATPAK_MAJOR_VERSION=0 FLATPAK_MINOR_VERSION=11 -FLATPAK_MICRO_VERSION=7 -FLATPAK_EXTRA_VERSION= +FLATPAK_MICRO_VERSION=8 +FLATPAK_EXTRA_VERSION=.3 FLATPAK_INTERFACE_AGE=0 -FLATPAK_VERSION=0.11.7 +FLATPAK_VERSION=0.11.8.3 @@ -18590,12 +18871,12 @@ -LT_VERSION_INFO="1107:0:1107" +LT_VERSION_INFO="1108:0:1108" LT_CURRENT_MINUS_AGE=0 -ac_config_files="$ac_config_files Makefile doc/Makefile doc/reference/Makefile flatpak.pc lib/flatpak-version-macros.h doc/reference/version.xml doc/flatpak-docs.xml po/Makefile.in" +ac_config_files="$ac_config_files Makefile doc/Makefile doc/reference/Makefile flatpak.pc common/flatpak-version-macros.h doc/reference/version.xml doc/flatpak-docs.xml po/Makefile.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -19203,7 +19484,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Flatpak $as_me 0.11.7, which was +This file was extended by Flatpak $as_me 0.11.8.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19270,7 +19551,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Flatpak config.status 0.11.7 +Flatpak config.status 0.11.8.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -19697,7 +19978,7 @@ "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/reference/Makefile") CONFIG_FILES="$CONFIG_FILES doc/reference/Makefile" ;; "flatpak.pc") CONFIG_FILES="$CONFIG_FILES flatpak.pc" ;; - "lib/flatpak-version-macros.h") CONFIG_FILES="$CONFIG_FILES lib/flatpak-version-macros.h" ;; + "common/flatpak-version-macros.h") CONFIG_FILES="$CONFIG_FILES common/flatpak-version-macros.h" ;; "doc/reference/version.xml") CONFIG_FILES="$CONFIG_FILES doc/reference/version.xml" ;; "doc/flatpak-docs.xml") CONFIG_FILES="$CONFIG_FILES doc/flatpak-docs.xml" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; diff -Nru flatpak-0.11.7/configure.ac flatpak-0.11.8.3/configure.ac --- flatpak-0.11.7/configure.ac 2018-05-03 07:25:50.000000000 +0100 +++ flatpak-0.11.8.3/configure.ac 2018-06-13 11:11:42.000000000 +0100 @@ -15,8 +15,8 @@ m4_define([flatpak_major_version], [0]) m4_define([flatpak_minor_version], [11]) -m4_define([flatpak_micro_version], [7]) -m4_define([flatpak_extra_version], []) +m4_define([flatpak_micro_version], [8]) +m4_define([flatpak_extra_version], [.3]) m4_define([flatpak_interface_age], [0]) m4_define([flatpak_binary_age], [m4_eval(10000 * flatpak_major_version + 100 * flatpak_minor_version + flatpak_micro_version)]) @@ -30,8 +30,8 @@ [http://flatpak.org/]) GLIB_REQS=2.44 -SYSTEM_BWRAP_REQS=0.1.8 -OSTREE_REQS=2017.14 +SYSTEM_BWRAP_REQS=0.2.1 +OSTREE_REQS=2017.15 OSTREE_P2P_REQS=2018.2 AC_USE_SYSTEM_EXTENSIONS @@ -40,6 +40,7 @@ AC_PROG_CC AM_PROG_CC_C_O AC_DISABLE_STATIC +AC_PROG_CC_STDC LT_PREREQ([2.2.6]) LT_INIT([disable-static]) @@ -264,26 +265,27 @@ [SUDO_BIN="sudo"], [SUDO_BIN=""]) AC_SUBST([SUDO_BIN]) -# Do we enable building peer to peer support using libostree’s experimental (non-stable) API? -# If so, OSTREE_ENABLE_EXPERIMENTAL_API needs to be #defined before ostree.h is -# included. -AC_ARG_ENABLE([p2p], - [AS_HELP_STRING([--enable-p2p], - [Enable unstable peer to peer support [default=no]])],, - [enable_p2p=no]) -AS_IF([test x$enable_p2p = xyes],[ - PKG_CHECK_MODULES(OSTREE, [ostree-1 >= $OSTREE_P2P_REQS]) +# Decide whether to build with peer to peer support. This requires API in +# libostree which before 2018.6 was experimental. +#FIXME: Clean up when flatpak depends on 2018.6 +enable_p2p=no +PKG_CHECK_MODULES(OSTREE_P2P_REQ, [ostree-1 >= $OSTREE_P2P_REQS],[ ostree_features=$($PKG_CONFIG --variable=features ostree-1) AS_CASE(["$ostree_features"], - [*experimental*],[have_ostree_experimental=yes]) + [*experimental*],[have_ostree_experimental=yes], + [*p2p*],[have_ostree_p2p=yes]) - AS_IF([test "x$have_ostree_experimental" != "xyes"], - [AC_MSG_ERROR([Experimental API not found in ostree-1, which is needed for --enable-p2p. OSTree must be compiled with --enable-experimental-api.])]) - - AC_DEFINE([OSTREE_ENABLE_EXPERIMENTAL_API],[1],[Define if libostree experimental API should be enabled]) - AC_DEFINE([FLATPAK_ENABLE_P2P],[1],[Define if peer to peer support should be enabled]) -]) + AS_IF([test "x$have_ostree_experimental" != "xyes" && test "x$have_ostree_p2p" != "xyes"],[ + AC_MSG_WARN([Experimental/P2P API not found in ostree-1, so flatpak will be compiled without P2P support. OSTree < 2018.6 must be compiled with --enable-experimental-api.]) + ],[ + enable_p2p=yes + AC_DEFINE([FLATPAK_ENABLE_P2P],[1],[Define if peer to peer support should be enabled]) + AS_IF([test "x$have_ostree_experimental" == "xyes"],[ + AC_DEFINE([OSTREE_ENABLE_EXPERIMENTAL_API],[1],[Define if libostree experimental API should be enabled]) + ]) + ]) +], :) AM_CONDITIONAL([ENABLE_P2P],[test x$enable_p2p = xyes]) AC_ARG_WITH(system-install-dir, @@ -436,7 +438,7 @@ doc/Makefile doc/reference/Makefile flatpak.pc -lib/flatpak-version-macros.h +common/flatpak-version-macros.h doc/reference/version.xml doc/flatpak-docs.xml po/Makefile.in diff -Nru flatpak-0.11.7/data/org.freedesktop.Flatpak.xml flatpak-0.11.8.3/data/org.freedesktop.Flatpak.xml --- flatpak-0.11.7/data/org.freedesktop.Flatpak.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/data/org.freedesktop.Flatpak.xml 2018-06-11 14:52:37.000000000 +0100 @@ -30,6 +30,10 @@ + + + + @@ -128,6 +132,10 @@ + + + + diff -Nru flatpak-0.11.7/dbus-proxy/dbus-proxy.c flatpak-0.11.8.3/dbus-proxy/dbus-proxy.c --- flatpak-0.11.7/dbus-proxy/dbus-proxy.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/dbus-proxy/dbus-proxy.c 2018-05-30 13:58:57.000000000 +0100 @@ -33,12 +33,45 @@ static GList *proxies; static int sync_fd = -1; -static int -parse_generic_args (int n_args, const char *args[]) +static void +add_args (GBytes *bytes, + GPtrArray *args, + int pos) { - if (g_str_has_prefix (args[0], "--fd=")) + gsize data_len, remainder_len; + const guchar *data = g_bytes_get_data (bytes, &data_len); + guchar *s; + const guchar *remainder; + + remainder = data; + remainder_len = data_len; + s = memchr (remainder, 0, remainder_len); + while (s) { - const char *fd_s = args[0] + strlen ("--fd="); + gsize len = s - remainder; + char *arg = g_strndup ((char *)remainder, len); + g_ptr_array_insert (args, pos++, arg); + remainder = s + 1; + remainder_len -= len + 1; + s = memchr (remainder, 0, remainder_len); + } + + if (remainder_len) + { + char *arg = g_strndup ((char *)remainder, remainder_len); + g_ptr_array_insert (args, pos++, arg); + } +} + + +static gboolean +parse_generic_args (GPtrArray *args, int *args_i) +{ + const char *arg = g_ptr_array_index (args, *args_i); + + if (g_str_has_prefix (arg, "--fd=")) + { + const char *fd_s = arg + strlen ("--fd="); char *endptr; int fd; @@ -46,131 +79,178 @@ if (fd < 0 || endptr == fd_s || *endptr != 0) { g_printerr ("Invalid fd %s\n", fd_s); - return -1; + return FALSE; } sync_fd = fd; - return 1; + *args_i += 1; + + return TRUE; + } + else if (g_str_has_prefix (arg, "--args=")) + { + const char *fd_s = arg + strlen ("--args="); + char *endptr; + int fd; + g_autoptr(GBytes) data = NULL; + g_autoptr(GError) error = NULL; + + fd = strtol (fd_s, &endptr, 10); + if (fd < 0 || endptr == fd_s || *endptr != 0) + { + g_printerr ("Invalid --args fd %s\n", fd_s); + return FALSE; + } + + data = glnx_fd_readall_bytes (fd, NULL, &error); + + if (data == NULL) + { + g_printerr ("Failed to load --args: %s\n", error->message); + return FALSE; + } + + *args_i += 1; + + add_args (data, args, *args_i); + + return TRUE; } else { - g_printerr ("Unknown argument %s\n", args[0]); - return -1; + g_printerr ("Unknown argument %s\n", arg); + return FALSE; } } -static int -start_proxy (int n_args, const char *args[]) +static gboolean +start_proxy (GPtrArray *args, int *args_i) { g_autoptr(FlatpakProxy) proxy = NULL; g_autoptr(GError) error = NULL; const char *bus_address, *socket_path; - int n; + const char *arg; - n = 0; - if (n_args < n + 1 || args[n][0] == '-') + if (*args_i >= args->len || ((char *)g_ptr_array_index (args, *args_i))[0] == '-') { g_printerr ("No bus address given\n"); - return -1; + return FALSE; } - bus_address = args[n++]; - if (n_args < n + 1 || args[n][0] == '-') + bus_address = g_ptr_array_index (args, *args_i); + *args_i += 1; + + if (*args_i >= args->len || ((char *)g_ptr_array_index (args, *args_i))[0] == '-') { g_printerr ("No socket path given\n"); - return -1; + return FALSE; } - socket_path = args[n++]; + + socket_path = g_ptr_array_index (args, *args_i); + *args_i += 1; proxy = flatpak_proxy_new (bus_address, socket_path); - while (n < n_args) + while (*args_i < args->len) { - if (args[n][0] != '-') + arg = g_ptr_array_index (args, *args_i); + + if (arg[0] != '-') break; - if (g_str_has_prefix (args[n], "--see=") || - g_str_has_prefix (args[n], "--talk=") || - g_str_has_prefix (args[n], "--filter=") || - g_str_has_prefix (args[n], "--own=")) + if (g_str_has_prefix (arg, "--see=") || + g_str_has_prefix (arg, "--talk=") || + g_str_has_prefix (arg, "--own=")) { FlatpakPolicy policy = FLATPAK_POLICY_SEE; - g_autofree char *name = NULL; + g_autofree char *name = g_strdup (strchr (arg, '=') + 1); gboolean wildcard = FALSE; - if (args[n][2] == 't') + if (arg[2] == 't') policy = FLATPAK_POLICY_TALK; - else if (args[n][2] == 'f') - policy = FLATPAK_POLICY_FILTERED; - else if (args[n][2] == 'o') + else if (arg[2] == 'o') policy = FLATPAK_POLICY_OWN; - name = g_strdup (strchr (args[n], '=') + 1); + if (g_str_has_suffix (name, ".*")) + { + name[strlen (name) - 2] = 0; + wildcard = TRUE; + } - if (policy == FLATPAK_POLICY_FILTERED) + if (name[0] == ':' || !g_dbus_is_name (name)) { - char *rule = strchr (name, '='); - if (rule != NULL) - { - *rule++ = 0; - flatpak_proxy_add_filter (proxy, name, rule); - } + g_printerr ("'%s' is not a valid dbus name\n", name); + return FALSE; } - else + + flatpak_proxy_add_policy (proxy, name, wildcard, policy); + + *args_i += 1; + } + else if (g_str_has_prefix (arg, "--call=") || + g_str_has_prefix (arg, "--broadcast=")) + { + g_autofree char *rest = g_strdup (strchr (arg, '=') + 1); + char *name = rest; + char *rule; + char *name_end = strchr (rest, '='); + gboolean wildcard = FALSE; + + if (name_end == NULL) { - if (g_str_has_suffix (name, ".*")) - { - name[strlen (name) - 2] = 0; - wildcard = TRUE; - } + g_printerr ("'%s' is not a valid name + rule\n", rest); + return FALSE; } - if (name[0] == ':' || !g_dbus_is_name (name)) + *name_end = 0; + rule = name_end + 1; + + if (g_str_has_suffix (name, ".*")) { - g_printerr ("'%s' is not a valid dbus name\n", name); - return -1; + name[strlen (name) - 2] = 0; + wildcard = TRUE; } - if (wildcard) - flatpak_proxy_add_wildcarded_policy (proxy, name, policy); + if (g_str_has_prefix (arg, "--call=")) + flatpak_proxy_add_call_rule (proxy, name, wildcard, rule); else - flatpak_proxy_add_policy (proxy, name, policy); + flatpak_proxy_add_broadcast_rule (proxy, name, wildcard, rule); + + *args_i += 1; } - else if (g_str_equal (args[n], "--log")) + else if (g_str_equal (arg, "--log")) { flatpak_proxy_set_log_messages (proxy, TRUE); + *args_i += 1; } - else if (g_str_equal (args[n], "--filter")) + else if (g_str_equal (arg, "--filter")) { flatpak_proxy_set_filter (proxy, TRUE); + *args_i += 1; } - else if (g_str_equal (args[n], "--sloppy-names")) + else if (g_str_equal (arg, "--sloppy-names")) { /* This means we're reporing the name changes for all unique names, which is needed for the a11y bus */ flatpak_proxy_set_sloppy_names (proxy, TRUE); + *args_i += 1; } else { - int res = parse_generic_args (n_args - n, &args[n]); - if (res == -1) - return -1; - - n += res - 1; /* res - 1, because we ++ below */ + if (!parse_generic_args (args, args_i)) + return FALSE; } - - n++; } if (!flatpak_proxy_start (proxy, &error)) { g_printerr ("Failed to start proxy for %s: %s\n", bus_address, error->message); - return -1; + return FALSE; } proxies = g_list_prepend (proxies, g_object_ref (proxy)); - return n; + return TRUE; } static gboolean @@ -191,30 +271,26 @@ main (int argc, const char *argv[]) { GMainLoop *service_loop; - int n_args, res; - const char **args; + int i, args_i; + g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free); - n_args = argc - 1; - args = &argv[1]; + for (i = 1; i < argc; i++) + g_ptr_array_add (args, g_strdup ((char *)argv[i])); - while (n_args > 0) + args_i = 0; + while (args_i < args->len) { - if (args[0][0] == '-') + const char *arg = g_ptr_array_index (args, args_i); + if (arg[0] == '-') { - res = parse_generic_args (n_args, &args[0]); - if (res == -1) + if (!parse_generic_args (args, &args_i)) return 1; } else { - res = start_proxy (n_args, args); - if (res == -1) + if (!start_proxy (args, &args_i)) return 1; } - - g_assert (res > 0); - n_args -= res; - args += res; } if (proxies == NULL) diff -Nru flatpak-0.11.7/dbus-proxy/flatpak-proxy.c flatpak-0.11.8.3/dbus-proxy/flatpak-proxy.c --- flatpak-0.11.7/dbus-proxy/flatpak-proxy.c 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/dbus-proxy/flatpak-proxy.c 2018-05-30 13:58:57.000000000 +0100 @@ -47,9 +47,9 @@ * initial policy is that the the user is only allowed to TALK to the * bus itself (org.freedesktop.DBus, or no destination specified), and * TALK to its own unique id. All other clients are invisible. The - * well-known names can be specified exactly, or as a simple one-level - * wildcard like "org.foo.*" which matches "org.foo.bar", but not - * "org.foobar" or "org.foo.bar.gazonk". + * well-known names can be specified exactly, or as a arg0namespace + * wildcards like "org.foo.*" which matches "org.foo", "org.foo.bar", + * and "org.foo.bar.gazonk", but not "org.foobar". * * Polices are specified for well-known names, but they also affect * the owner of that name, so that the policy for a unique id is the @@ -73,9 +73,6 @@ * You can call the GetXXX methods on the name/id to get e.g. the peer pid * You get AccessDenied rather than NameHasNoOwner when sending messages to the name/id * - * FILTERED: - * You can send *some* method calls to the name (not id) - * * TALK: * You can send any method calls and signals to the name/id * You will receive broadcast signals from the name/id (if you have a match rule for them) @@ -84,14 +81,22 @@ * OWN: * You are allowed to call RequestName/ReleaseName/ListQueuedOwners on the name. * - * The policy applies only to signals and method calls. All replies - * (errors or method returns) are allowed once for an outstanding - * method call, and never otherwise. + * Additionally, there can be more detailed filters installed that + * limits what messages you can send to and receive broadcasts from. + * However, if you can *ever* call or recieve broadcasts from a name (even if + * filtered to some subset of paths/interfaces) its visibility is considered + * to be as TALK. + * + * The policy applies only to outgoing signals and method calls and + * incoming broadcast. All replies (errors or method returns) are + * allowed once for an outstanding method call, and never + * otherwise. * * Every peer on the bus is considered priviledged, and we thus trust - * it. So we rely on similar proxies to be running for all untrusted - * clients. Any such priviledged peer is allowed to send method call - * or unicast signal messages to the proxied client. Once another peer + * it and don't apply any filtering (except broadcasts). So we rely on + * similar proxies to be running for all untrusted clients. Any such + * priviledged peer is allowed to send method call or unicast signal + * messages to the proxied client. Once another peer * sends you a message the unique id of that peer is now made visible * (policy SEE) to the proxied client, allowing the client to track * caller lifetimes via NameOwnerChanged signals. @@ -155,6 +160,10 @@ * * When we get a reply to the initial Hello request we give * our own assigned unique id policy TALK. * + * There is also a mode called "sloppy-names" where you automatically get + * SEE access to all the unique names on the bus. This is used only for + * the a11y bus. + * * All messages sent to the bus itself are fully demarshalled * and handled on a per-method basis: * @@ -222,9 +231,23 @@ guint32 unix_fds; } Header; +typedef enum { + FILTER_TYPE_CALL = 1<<0, + FILTER_TYPE_BROADCAST = 1<<1, +} FilterTypeMask; + +#define FILTER_TYPE_ALL (FILTER_TYPE_CALL|FILTER_TYPE_BROADCAST) + typedef struct { + char *name; + gboolean name_is_subtree; + FlatpakPolicy policy; + + /* More detailed filter */ + FilterTypeMask types; char *path; + gboolean path_is_subtree; char *interface; char *member; } Filter; @@ -272,6 +295,7 @@ GHashTable *get_owner_reply; GHashTable *unique_id_policy; + GHashTable *unique_id_owned_names; }; typedef struct @@ -292,8 +316,6 @@ gboolean filter; gboolean sloppy_names; - GHashTable *wildcard_policy; - GHashTable *policy; GHashTable *filters; }; @@ -328,6 +350,12 @@ static void stop_reading (ProxySide *side); static void +string_list_free (GList *filters) +{ + g_list_free_full (filters, (GDestroyNotify)g_free); +} + +static void buffer_unref (Buffer *buffer) { g_assert (buffer->refcount > 0); @@ -377,6 +405,7 @@ g_hash_table_destroy (client->rewrite_reply); g_hash_table_destroy (client->get_owner_reply); g_hash_table_destroy (client->unique_id_policy); + g_hash_table_destroy (client->unique_id_owned_names); free_side (&client->client_side); free_side (&client->bus_side); @@ -413,6 +442,7 @@ client->rewrite_reply = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); client->get_owner_reply = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); client->unique_id_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + client->unique_id_owned_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)string_list_free); } static FlatpakProxyClient * @@ -431,39 +461,6 @@ return client; } -static FlatpakPolicy -flatpak_proxy_get_wildcard_policy (FlatpakProxy *proxy, - const char *_name) -{ - guint policy, wildcard_policy = 0; - char *dot; - g_autofree char *name = g_strdup (_name); - - dot = name + strlen (name); - while (dot) - { - *dot = 0; - policy = GPOINTER_TO_INT (g_hash_table_lookup (proxy->wildcard_policy, name)); - wildcard_policy = MAX (wildcard_policy, policy); - dot = strrchr (name, '.'); - } - - return wildcard_policy; -} - -static FlatpakPolicy -flatpak_proxy_get_policy (FlatpakProxy *proxy, - const char *name) -{ - guint policy, wildcard_policy; - - policy = GPOINTER_TO_INT (g_hash_table_lookup (proxy->policy, name)); - - wildcard_policy = flatpak_proxy_get_wildcard_policy (proxy, name); - - return MAX (policy, wildcard_policy); -} - void flatpak_proxy_set_filter (FlatpakProxy *proxy, gboolean filter) @@ -485,29 +482,10 @@ proxy->log_messages = log; } -void -flatpak_proxy_add_policy (FlatpakProxy *proxy, - const char *name, - FlatpakPolicy policy) -{ - guint current_policy = GPOINTER_TO_INT (g_hash_table_lookup (proxy->policy, name)); - - current_policy = MAX (policy, current_policy); - - g_hash_table_replace (proxy->policy, g_strdup (name), GINT_TO_POINTER (current_policy)); -} - -void -flatpak_proxy_add_wildcarded_policy (FlatpakProxy *proxy, - const char *name, - FlatpakPolicy policy) -{ - g_hash_table_replace (proxy->wildcard_policy, g_strdup (name), GINT_TO_POINTER (policy)); -} - static void filter_free (Filter *filter) { + g_free (filter->name); g_free (filter->path); g_free (filter->interface); g_free (filter->member); @@ -520,50 +498,138 @@ g_list_free_full (filters, (GDestroyNotify)filter_free); } -/* rules are of the form [org.the.interface.[method|*]][@/obj/path] */ + static Filter * -filter_new (const char *rule) +filter_new (const char *name, + gboolean name_is_subtree, + FlatpakPolicy policy) { Filter *filter = g_new0 (Filter, 1); + + filter->name = g_strdup (name); + filter->name_is_subtree = name_is_subtree; + filter->policy = policy; + filter->types = FILTER_TYPE_ALL; + + return filter; +} + +// rules are of the form [*|org.the.interface.[method|*]]|[@/obj/path[/*]] +static Filter * +filter_new_from_rule (const char *name, + gboolean name_is_subtree, + FilterTypeMask types, + const char *rule) +{ + Filter *filter; const char *obj_path_start = NULL; const char *method_end = NULL; + filter = filter_new (name, name_is_subtree, FLATPAK_POLICY_TALK); + filter->types = types; + obj_path_start = strchr (rule, '@'); if (obj_path_start && obj_path_start[1] != 0) - filter->path = g_strdup (obj_path_start + 1); + { + filter->path = g_strdup (obj_path_start + 1); + + if (g_str_has_suffix (filter->path, "/*")) + { + filter->path_is_subtree = TRUE; + filter->path[strlen (filter->path) - 2] = 0; + } + } if (obj_path_start != NULL) method_end = obj_path_start; else method_end = rule + strlen(rule); - if (rule[0] != '@') + if (method_end != rule) { - filter->interface = g_strndup (rule, method_end - rule); - char *dot = strrchr (filter->interface, '.'); - if (dot != NULL) + if (rule[0] == '*') + { + /* Both interface and method wildcarded */ + } + else { - *dot = 0; - if (strcmp (dot+1, "*") != 0) - filter->member = g_strdup (dot + 1); - } + filter->interface = g_strndup (rule, method_end - rule); + char *dot = strrchr (filter->interface, '.'); + if (dot != NULL) + { + *dot = 0; + if (strcmp (dot+1, "*") != 0) + filter->member = g_strdup (dot + 1); + } + } } return filter; } +static gboolean +filter_matches (Filter *filter, + FilterTypeMask type, + const char *path, + const char *interface, + const char *member) +{ + if ((filter->types & type) == 0) + return FALSE; -void + if (filter->path) + { + if (path == NULL) + return FALSE; + + if (filter->path_is_subtree) + { + gsize filter_path_len = strlen (filter->path); + if (strncmp (path, filter->path, filter_path_len) != 0 || + (path[filter_path_len] != 0 && path[filter_path_len] != '/')) + return FALSE; + } + else if (strcmp (filter->path, path) != 0) + return FALSE; + } + + if (filter->interface && g_strcmp0 (filter->interface, interface) != 0) + return FALSE; + + if (filter->member && g_strcmp0 (filter->member, member) != 0) + return FALSE; + + return TRUE; +} + +static gboolean +any_filter_matches (GList *filters, + FilterTypeMask type, + const char *path, + const char *interface, + const char *member) +{ + GList *l; + + for (l = filters; l != NULL; l = l->next) + { + Filter *filter = l->data; + if (filter_matches (filter, type, path, interface, member)) + return TRUE; + } + + return FALSE; +} + + +static void flatpak_proxy_add_filter (FlatpakProxy *proxy, - const char *name, - const char *rule) + Filter *filter) { - Filter *filter; GList *filters, *new_filters; - filter = filter_new (rule); if (g_hash_table_lookup_extended (proxy->filters, - name, + filter->name, NULL, (void **)&filters)) { new_filters = g_list_append (filters, filter); @@ -572,10 +638,43 @@ else { filters = g_list_append (NULL, filter); - g_hash_table_insert (proxy->filters, g_strdup (name), filters); + g_hash_table_insert (proxy->filters, g_strdup (filter->name), filters); } } +void +flatpak_proxy_add_policy (FlatpakProxy *proxy, + const char *name, + gboolean name_is_subtree, + FlatpakPolicy policy) +{ + Filter *filter = filter_new (name, name_is_subtree, policy); + + flatpak_proxy_add_filter (proxy, filter); +} + +void +flatpak_proxy_add_call_rule (FlatpakProxy *proxy, + const char *name, + gboolean name_is_subtree, + const char *rule) +{ + Filter *filter = filter_new_from_rule (name, name_is_subtree, FILTER_TYPE_CALL, rule); + + flatpak_proxy_add_filter (proxy, filter); +} + +void +flatpak_proxy_add_broadcast_rule (FlatpakProxy *proxy, + const char *name, + gboolean name_is_subtree, + const char *rule) +{ + Filter *filter = filter_new_from_rule (name, name_is_subtree, FILTER_TYPE_BROADCAST, rule); + + flatpak_proxy_add_filter (proxy, filter); +} + static void flatpak_proxy_finalize (GObject *object) { @@ -586,8 +685,6 @@ g_assert (proxy->clients == NULL); - g_hash_table_destroy (proxy->policy); - g_hash_table_destroy (proxy->wildcard_policy); g_hash_table_destroy (proxy->filters); g_free (proxy->socket_path); @@ -1304,16 +1401,88 @@ } } + +static Filter *match_all[FLATPAK_POLICY_OWN+1] = { NULL }; + + static FlatpakPolicy -flatpak_proxy_client_get_policy (FlatpakProxyClient *client, const char *source) -{ +flatpak_proxy_client_get_max_policy_and_matched (FlatpakProxyClient *client, + const char *source, + GList **matched_filters) +{ + GList *names, *filters, *l; + FlatpakPolicy max_policy = FLATPAK_POLICY_NONE; + g_autofree char *name = NULL; + gboolean exact_name_match; + char *dot; + + if (match_all[FLATPAK_POLICY_SEE] == NULL) + { + match_all[FLATPAK_POLICY_SEE] = filter_new ("", FALSE, FLATPAK_POLICY_SEE); + match_all[FLATPAK_POLICY_TALK] = filter_new ("", FALSE, FLATPAK_POLICY_TALK); + match_all[FLATPAK_POLICY_OWN] = filter_new ("", FALSE, FLATPAK_POLICY_OWN); + } + if (source == NULL) - return FLATPAK_POLICY_TALK; /* All clients can talk to the bus itself */ + { + if (matched_filters) + *matched_filters = g_list_append (*matched_filters, match_all[FLATPAK_POLICY_TALK]); + + return FLATPAK_POLICY_TALK; /* All clients can talk to the bus itself */ + } if (source[0] == ':') - return GPOINTER_TO_UINT (g_hash_table_lookup (client->unique_id_policy, source)); + { + /* Default to the unique id policy, i.e. TALK for self, and SEE for trusted peers */ + max_policy = GPOINTER_TO_UINT (g_hash_table_lookup (client->unique_id_policy, source)); + if (max_policy > FLATPAK_POLICY_NONE && matched_filters) + *matched_filters = g_list_append (*matched_filters, match_all[max_policy]); + + /* Treat this as the merged list of filters for all the names the unique id ever owned */ + names = g_hash_table_lookup (client->unique_id_owned_names, source); + for (l = names; l != NULL; l = l->next) + { + const char *owned_name = l->data; + max_policy = MAX (max_policy, flatpak_proxy_client_get_max_policy_and_matched (client, owned_name, matched_filters)); + } + + + return max_policy; + } + + name = g_strdup (source); + exact_name_match = TRUE; + do + { + filters = g_hash_table_lookup (client->proxy->filters, name); + + for (l = filters; l != NULL; l = l->next) + { + Filter *filter = l->data; + + if (exact_name_match || filter->name_is_subtree) + { + max_policy = MAX (max_policy, filter->policy); + if (matched_filters) + *matched_filters = g_list_append (*matched_filters, filter); + } + } + + exact_name_match = FALSE; + dot = strrchr (name, '.'); + if (dot != NULL) + *dot = 0; + } + while (dot != NULL); - return flatpak_proxy_get_policy (client->proxy, source); + return max_policy; +} + +static FlatpakPolicy +flatpak_proxy_client_get_max_policy (FlatpakProxyClient *client, + const char *source) +{ + return flatpak_proxy_client_get_max_policy_and_matched (client, source, NULL); } static void @@ -1330,14 +1499,23 @@ } } + static void -flatpak_proxy_client_update_unique_id_policy_from_name (FlatpakProxyClient *client, - const char *unique_id, - const char *as_name) +flatpak_proxy_client_add_unique_id_owned_name (FlatpakProxyClient *client, + const char *unique_id, + const char *owned_name) { - flatpak_proxy_client_update_unique_id_policy (client, + GList *names; + gboolean already_added; + + names = NULL; + already_added = g_hash_table_lookup_extended (client->unique_id_owned_names, unique_id, - flatpak_proxy_get_policy (client->proxy, as_name)); + NULL, (void **)&names); + names = g_list_append (names, g_strdup (owned_name)); + + if (!already_added) + g_hash_table_insert (client->unique_id_owned_names, g_strdup (unique_id), names); } @@ -1482,6 +1660,7 @@ { FlatpakPolicy policy; const char *method; + g_autoptr(GList) filters = NULL; if (header->has_reply_serial) { @@ -1494,34 +1673,25 @@ return HANDLE_PASS; } - policy = flatpak_proxy_client_get_policy (client, header->destination); + policy = flatpak_proxy_client_get_max_policy_and_matched (client, header->destination, &filters); if (policy < FLATPAK_POLICY_SEE) return HANDLE_HIDE; - if (policy < FLATPAK_POLICY_FILTERED) + if (policy < FLATPAK_POLICY_TALK) return HANDLE_DENY; - if (policy == FLATPAK_POLICY_FILTERED) + if (!is_for_bus (header)) { - GList *filters = NULL, *l; - - if (header->destination) - filters = g_hash_table_lookup (client->proxy->filters, header->destination); - for (l = filters; l != NULL; l = l->next) - { - Filter *filter = l->data; - - if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_CALL && - (filter->path == NULL || g_strcmp0 (filter->path, header->path) == 0) && - (filter->interface == NULL || g_strcmp0 (filter->interface, header->interface) == 0) && - (filter->member == NULL || g_strcmp0 (filter->member, header->member) == 0)) - return HANDLE_PASS; - } + if (policy == FLATPAK_POLICY_OWN || + any_filter_matches (filters, FILTER_TYPE_CALL, + header->path, + header->interface, + header->member)) + return HANDLE_PASS; return HANDLE_DENY; } - if (!is_for_bus (header)) - return HANDLE_PASS; + /* Its a bus call */ if (is_introspection_call (header)) { @@ -1657,7 +1827,7 @@ g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING)) { name = g_variant_get_string (arg0, NULL); - name_policy = flatpak_proxy_client_get_policy (client, name); + name_policy = flatpak_proxy_client_get_max_policy (client, name); if (has_policy) *has_policy = name_policy; @@ -1693,7 +1863,7 @@ g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY); for (i = 0; names[i] != NULL; i++) { - if (flatpak_proxy_client_get_policy (client, names[i]) >= FLATPAK_POLICY_SEE) + if (flatpak_proxy_client_get_max_policy (client, names[i]) >= FLATPAK_POLICY_SEE) g_variant_builder_add (&builder, "s", names[i]); } g_free (names); @@ -1723,7 +1893,7 @@ { GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL); GVariant *body, *arg0, *arg1, *arg2; - const gchar *name, *old, *new; + const gchar *name, *new; gboolean filter = TRUE; if (message == NULL || @@ -1737,19 +1907,15 @@ return TRUE; name = g_variant_get_string (arg0, NULL); - old = g_variant_get_string (arg1, NULL); new = g_variant_get_string (arg2, NULL); - if (flatpak_proxy_client_get_policy (client, name) >= FLATPAK_POLICY_SEE || + if (flatpak_proxy_client_get_max_policy (client, name) >= FLATPAK_POLICY_SEE || (client->proxy->sloppy_names && name[0] == ':')) { if (name[0] != ':') { - if (old[0] != 0) - flatpak_proxy_client_update_unique_id_policy_from_name (client, old, name); - if (new[0] != 0) - flatpak_proxy_client_update_unique_id_policy_from_name (client, new, name); + flatpak_proxy_client_add_unique_id_owned_name (client, new, name); } filter = FALSE; @@ -1845,12 +2011,25 @@ gpointer key, value; gboolean has_wildcards = FALSE; - g_hash_table_iter_init (&iter, client->proxy->policy); + g_hash_table_iter_init (&iter, client->proxy->filters); while (g_hash_table_iter_next (&iter, &key, &value)) { const char *name = key; + GList *filters = value; + gboolean name_needs_subtree = FALSE; GDBusMessage *message; GVariant *match; + GList *l; + + for (l = filters; l != NULL; l = l->next) + { + Filter *filter = l->data; + if (filter->name_is_subtree) + { + name_needs_subtree = TRUE; + break; + } + } if (strcmp (name, "org.freedesktop.DBus") == 0) continue; @@ -1858,45 +2037,32 @@ /* AddMatch the name so we get told about ownership changes. Do it before the GetNameOwner to avoid races */ message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "AddMatch"); - match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='%s'", name); + if (name_needs_subtree) + match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0namespace='%s'", name); + else + match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='%s'", name); g_dbus_message_set_body (message, g_variant_new_tuple (&match, 1)); queue_fake_message (client, message, EXPECTED_REPLY_FILTER); if (client->proxy->log_messages) - g_print ("C%d: -> org.freedesktop.DBus fake AddMatch for %s\n", client->last_serial, name); - - /* Get the current owner of the name (if any) so we can apply policy to it */ - message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner"); - g_dbus_message_set_body (message, g_variant_new ("(s)", name)); - queue_fake_message (client, message, EXPECTED_REPLY_FAKE_GET_NAME_OWNER); - g_hash_table_replace (client->get_owner_reply, GINT_TO_POINTER (client->last_serial), g_strdup (name)); - - if (client->proxy->log_messages) - g_print ("C%d: -> org.freedesktop.DBus fake GetNameOwner for %s\n", client->last_serial, name); - } - - /* Same for wildcard proxies. Only here we don't know the actual names to GetNameOwner for, so we have to - list all current names */ - g_hash_table_iter_init (&iter, client->proxy->wildcard_policy); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *name = key; - GDBusMessage *message; - GVariant *match; - - has_wildcards = TRUE; + g_print ("C%d: -> org.freedesktop.DBus fake %sAddMatch for %s\n", client->last_serial, name_needs_subtree ? "wildcarded " : "", name); - /* AddMatch the name with arg0namespace so we get told about ownership changes to all subnames. - Do it before the GetNameOwner to avoid races */ - message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "AddMatch"); - match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0namespace='%s'", name); - g_dbus_message_set_body (message, g_variant_new_tuple (&match, 1)); - queue_fake_message (client, message, EXPECTED_REPLY_FILTER); + if (!name_needs_subtree) + { + /* Get the current owner of the name (if any) so we can apply policy to it */ + message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner"); + g_dbus_message_set_body (message, g_variant_new ("(s)", name)); + queue_fake_message (client, message, EXPECTED_REPLY_FAKE_GET_NAME_OWNER); + g_hash_table_replace (client->get_owner_reply, GINT_TO_POINTER (client->last_serial), g_strdup (name)); - if (client->proxy->log_messages) - g_print ("C%d: -> org.freedesktop.DBus fake AddMatch for %s.*\n", client->last_serial, name); + if (client->proxy->log_messages) + g_print ("C%d: -> org.freedesktop.DBus fake GetNameOwner for %s\n", client->last_serial, name); + } + else + has_wildcards = TRUE; /* Send ListNames below */ } + /* For wildcarded rules we don't know the actual names to GetNameOwner for, so we have to list all current names */ if (has_wildcards) { GDBusMessage *message; @@ -1913,6 +2079,8 @@ /* Stop reading from the client, to avoid incoming messages fighting with the ListNames roundtrip. We will start it again once we have handled the ListNames reply */ stop_reading (&client->client_side); + + /* Once we get the reply to this queue_wildcard_initial_name_ops() will be called and we continue there */ } } @@ -1931,14 +2099,14 @@ const gchar **names = g_variant_get_strv (arg0, NULL); int i; - /* Loop over all current names and get the owner for all the ones that match our wildcard + /* Loop over all current names and get the owner for all the ones that match our rules policies so that we can update the unique id policies for those */ for (i = 0; names[i] != NULL; i++) { const char *name = names[i]; if (name[0] != ':' && - flatpak_proxy_get_wildcard_policy (client->proxy, name) != FLATPAK_POLICY_NONE) + flatpak_proxy_client_get_max_policy (client, name) != FLATPAK_POLICY_NONE) { /* Get the current owner of the name (if any) so we can apply policy to it */ GDBusMessage *message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner"); @@ -2222,7 +2390,7 @@ if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) { g_autofree char *owner = get_arg0_string (buffer); - flatpak_proxy_client_update_unique_id_policy_from_name (client, owner, requested_name); + flatpak_proxy_client_add_unique_id_owned_name (client, owner, requested_name); } g_hash_table_remove (client->get_owner_reply, GINT_TO_POINTER (header->reply_serial)); @@ -2284,8 +2452,20 @@ /* All incoming broadcast signals are filtered according to policy */ if (header->type == G_DBUS_MESSAGE_TYPE_SIGNAL && header->destination == NULL) { - policy = flatpak_proxy_client_get_policy (client, header->sender); - if (policy < FLATPAK_POLICY_TALK) + g_autoptr(GList) filters = NULL; + gboolean filtered = TRUE; + + policy = flatpak_proxy_client_get_max_policy_and_matched (client, header->sender, &filters); + + if (policy == FLATPAK_POLICY_OWN || + (policy == FLATPAK_POLICY_TALK && + any_filter_matches (filters, FILTER_TYPE_BROADCAST, + header->path, + header->interface, + header->member))) + filtered = FALSE; + + if (filtered) { if (client->proxy->log_messages) g_print ("*FILTERED IN*\n"); @@ -2586,10 +2766,8 @@ static void flatpak_proxy_init (FlatpakProxy *proxy) { - proxy->policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); proxy->filters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)filter_list_free); - proxy->wildcard_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - flatpak_proxy_add_policy (proxy, "org.freedesktop.DBus", FLATPAK_POLICY_TALK); + flatpak_proxy_add_policy (proxy, "org.freedesktop.DBus", FALSE, FLATPAK_POLICY_TALK); } static void diff -Nru flatpak-0.11.7/dbus-proxy/flatpak-proxy.h flatpak-0.11.8.3/dbus-proxy/flatpak-proxy.h --- flatpak-0.11.7/dbus-proxy/flatpak-proxy.h 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/dbus-proxy/flatpak-proxy.h 2018-05-30 13:58:57.000000000 +0100 @@ -27,7 +27,6 @@ typedef enum { FLATPAK_POLICY_NONE, FLATPAK_POLICY_SEE, - FLATPAK_POLICY_FILTERED, FLATPAK_POLICY_TALK, FLATPAK_POLICY_OWN } FlatpakPolicy; @@ -52,13 +51,16 @@ gboolean sloppy_names); void flatpak_proxy_add_policy (FlatpakProxy *proxy, const char *name, + gboolean name_is_subtree, FlatpakPolicy policy); -void flatpak_proxy_add_wildcarded_policy (FlatpakProxy *proxy, - const char *name, - FlatpakPolicy policy); -void flatpak_proxy_add_filter (FlatpakProxy *proxy, - const char *name, - const char *rule); +void flatpak_proxy_add_call_rule (FlatpakProxy *proxy, + const char *name, + gboolean name_is_subtree, + const char *rule); +void flatpak_proxy_add_broadcast_rule (FlatpakProxy *proxy, + const char *name, + gboolean name_is_subtree, + const char *rule); gboolean flatpak_proxy_start (FlatpakProxy *proxy, GError **error); void flatpak_proxy_stop (FlatpakProxy *proxy); diff -Nru flatpak-0.11.7/debian/changelog flatpak-0.11.8.3/debian/changelog --- flatpak-0.11.7/debian/changelog 2018-05-03 22:19:31.000000000 +0100 +++ flatpak-0.11.8.3/debian/changelog 2018-06-14 01:04:17.000000000 +0100 @@ -1,3 +1,18 @@ +flatpak (0.11.8.3-0ubuntu0.1) bionic; urgency=medium + + * Update to 0.11.8.3 (LP: #1776307) + * New upstream release + - Remove --disable-document-portal, no longer necessary since 0.11.0 + - Install zsh completion functions + - debian/copyright: Update + - debian/control: Update bubblewrap and ostree dependencies + - debian/control: Depend on python3 for build-time tests + - Update symbols file for new ABI + - debian/test.sh: Output test logs in the build log, even on success + - debian/patches/debian/Use-Python-3-for-test-web-server.patch: Rebase + + -- Andrew Hayzen Thu, 14 Jun 2018 01:04:17 +0100 + flatpak (0.11.7-0ubuntu0.1) bionic-proposed; urgency=medium * Update to 0.11.7 (LP: #1767215) diff -Nru flatpak-0.11.7/debian/control flatpak-0.11.8.3/debian/control --- flatpak-0.11.7/debian/control 2018-05-03 22:19:31.000000000 +0100 +++ flatpak-0.11.8.3/debian/control 2018-06-14 01:04:17.000000000 +0100 @@ -10,7 +10,7 @@ attr , automake (>= 1.14.1), bison, - bubblewrap (>= 0.1.8), + bubblewrap (>= 0.2.1), ca-certificates , dbus, debhelper (>= 10~), @@ -33,7 +33,7 @@ libglib2.0-dev (>= 2.44), libgpgme-dev (>= 1.1.8), libjson-glib-dev, - libostree-dev (>= 2017.14), + libostree-dev (>= 2017.15), libpolkit-gobject-1-dev, libseccomp-dev, libsoup2.4-dev, @@ -42,6 +42,7 @@ libxml2-utils, ostree , procps, + python3 , shared-mime-info , xmlto , xsltproc , @@ -57,7 +58,7 @@ Package: flatpak Architecture: linux-any Depends: - bubblewrap (>= 0.1.8), + bubblewrap (>= 0.2.1), xdg-desktop-portal (>= 0.10), ${misc:Depends}, ${shlibs:Depends}, @@ -102,7 +103,7 @@ gnupg, gtk-update-icon-cache, hicolor-icon-theme, - ostree (>= 2017.14), + ostree (>= 2017.15), shared-mime-info, ${misc:Depends}, ${shlibs:Depends}, @@ -136,7 +137,7 @@ gir1.2-flatpak-1.0 (= ${binary:Version}), libflatpak0 (= ${binary:Version}), libglib2.0-dev, - libostree-dev (>= 2017.14), + libostree-dev (>= 2017.15), libxml2-dev (>= 2.4), pkg-config, ${misc:Depends}, @@ -166,7 +167,7 @@ Architecture: linux-any Section: libs Depends: - bubblewrap (>= 0.1.8), + bubblewrap (>= 0.2.1), ${misc:Depends}, ${shlibs:Depends}, Pre-Depends: diff -Nru flatpak-0.11.7/debian/copyright flatpak-0.11.8.3/debian/copyright --- flatpak-0.11.7/debian/copyright 2018-05-03 22:19:31.000000000 +0100 +++ flatpak-0.11.8.3/debian/copyright 2018-06-14 01:04:17.000000000 +0100 @@ -28,10 +28,12 @@ app/parse-datetime.y data/org.freedesktop.portal.Flatpak.xml tests/make-multi-collection-id-repo.sh + tests/test-build-update-repo.sh Copyright: © 1995-2015 Free Software Foundation, Inc. © 2017 Endless, Inc. © 2018 Red Hat, Inc + © 2018 Endless Mobile, Inc. License: LGPL-2+ Files: @@ -50,6 +52,12 @@ License: GPL-2+ with Autoconf exception Files: + common/valgrind-private.h +Copyright: + © 2000-2017 Julian Seward +License: bzip2-1.0.6 + +Files: debian/* Copyright: © 2015 David King @@ -130,3 +138,36 @@ permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. + +License: bzip2-1.0.6 + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + . + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + . + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + . + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff -Nru flatpak-0.11.7/debian/flatpak.install flatpak-0.11.8.3/debian/flatpak.install --- flatpak-0.11.7/debian/flatpak.install 2018-05-03 22:19:31.000000000 +0100 +++ flatpak-0.11.8.3/debian/flatpak.install 2018-06-14 01:04:17.000000000 +0100 @@ -21,6 +21,7 @@ usr/share/locale/*/LC_MESSAGES/flatpak.mo usr/share/polkit-1/actions usr/share/polkit-1/rules.d +usr/share/zsh/site-functions/_flatpak usr/share/zsh/vendor-completions usr/share/man/man1 usr/share/man/man5 usr/share/doc/flatpak/docbook.css diff -Nru flatpak-0.11.7/debian/libflatpak0.symbols flatpak-0.11.8.3/debian/libflatpak0.symbols --- flatpak-0.11.7/debian/libflatpak0.symbols 2018-05-03 22:19:31.000000000 +0100 +++ flatpak-0.11.8.3/debian/libflatpak0.symbols 2018-06-14 01:04:17.000000000 +0100 @@ -56,6 +56,7 @@ flatpak_installation_remove_remote@Base 0.5.2+git20160516 flatpak_installation_set_config_sync@Base 0.10.0 flatpak_installation_uninstall@Base 0.5.2 + flatpak_installation_uninstall_full@Base 0.11.8 flatpak_installation_update@Base 0.5.2 flatpak_installation_update_appstream_full_sync@Base 0.9.4 flatpak_installation_update_appstream_sync@Base 0.5.2 @@ -72,6 +73,7 @@ flatpak_installed_ref_get_type@Base 0.5.2 flatpak_installed_ref_load_metadata@Base 0.5.2 flatpak_oci_error_quark@Base 0.9.1 + flatpak_portal_error_get_type@Base 0.11.8 flatpak_portal_error_quark@Base 0.5.2+git20160516 flatpak_ref_format_ref@Base 0.5.2 flatpak_ref_get_arch@Base 0.5.2 @@ -85,6 +87,7 @@ flatpak_ref_parse@Base 0.5.2 flatpak_related_ref_get_subpaths@Base 0.6.7 flatpak_related_ref_get_type@Base 0.6.7 + flatpak_related_ref_should_autoprune@Base 0.11.8 flatpak_related_ref_should_delete@Base 0.6.7 flatpak_related_ref_should_download@Base 0.6.7 flatpak_remote_get_appstream_dir@Base 0.5.2 @@ -121,4 +124,29 @@ flatpak_remote_set_url@Base 0.5.2+git20160516 flatpak_remote_type_get_type@Base 0.9.8 flatpak_storage_type_get_type@Base 0.8.0 + flatpak_transaction_add_install@Base 0.11.8 + flatpak_transaction_add_install_bundle@Base 0.11.8 + flatpak_transaction_add_uninstall@Base 0.11.8 + flatpak_transaction_add_update@Base 0.11.8 + flatpak_transaction_error_details_get_type@Base 0.11.8 + flatpak_transaction_get_type@Base 0.11.8 + flatpak_transaction_is_empty@Base 0.11.8 + flatpak_transaction_new_for_installation@Base 0.11.8 + flatpak_transaction_operation_type_get_type@Base 0.11.8 + flatpak_transaction_progress_get_is_estimating@Base 0.11.8 + flatpak_transaction_progress_get_progress@Base 0.11.8 + flatpak_transaction_progress_get_status@Base 0.11.8 + flatpak_transaction_progress_get_type@Base 0.11.8 + flatpak_transaction_progress_set_update_frequency@Base 0.11.8 + flatpak_transaction_result_get_type@Base 0.11.8 + flatpak_transaction_run@Base 0.11.8 + flatpak_transaction_set_disable_dependencies@Base 0.11.8 + flatpak_transaction_set_disable_prune@Base 0.11.8 + flatpak_transaction_set_disable_related@Base 0.11.8 + flatpak_transaction_set_disable_static_deltas@Base 0.11.8 + flatpak_transaction_set_force_uninstall@Base 0.11.8 + flatpak_transaction_set_no_deploy@Base 0.11.8 + flatpak_transaction_set_no_pull@Base 0.11.8 + flatpak_transaction_set_reinstall@Base 0.11.8 + flatpak_uninstall_flags_get_type@Base 0.11.8 flatpak_update_flags_get_type@Base 0.5.2 diff -Nru flatpak-0.11.7/debian/patches/debian/Use-Python-3-for-test-web-server.patch flatpak-0.11.8.3/debian/patches/debian/Use-Python-3-for-test-web-server.patch --- flatpak-0.11.7/debian/patches/debian/Use-Python-3-for-test-web-server.patch 2018-03-11 16:00:02.000000000 +0000 +++ flatpak-0.11.8.3/debian/patches/debian/Use-Python-3-for-test-web-server.patch 2018-06-14 01:04:17.000000000 +0100 @@ -12,7 +12,7 @@ 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-webserver.sh b/tests/test-webserver.sh -index 2964ce9..c1f26d0 100755 +index 48e545c..fddc48d 100755 --- a/tests/test-webserver.sh +++ b/tests/test-webserver.sh @@ -6,7 +6,7 @@ dir=$1 @@ -22,10 +22,10 @@ -env PYTHONUNBUFFERED=1 setsid python -m SimpleHTTPServer 0 >${test_tmpdir}/httpd-output & +env PYTHONUNBUFFERED=1 setsid python3 -m http.server 0 >${test_tmpdir}/httpd-output & child_pid=$! + echo "Web server pid: $child_pid" >&2 - for x in $(seq 50); do -@@ -14,7 +14,7 @@ for x in $(seq 50); do - cp ${test_tmpdir}/httpd-output{,.tmp} +@@ -18,7 +18,7 @@ for x in $(seq 300); do + echo >&2 # If it's non-empty, see whether it matches our regexp if test -s ${test_tmpdir}/httpd-output.tmp; then - sed -e 's,Serving HTTP on 0.0.0.0 port \([0-9]*\) \.\.\.,\1,' < ${test_tmpdir}/httpd-output.tmp > ${test_tmpdir}/httpd-port @@ -33,3 +33,4 @@ if ! cmp ${test_tmpdir}/httpd-output.tmp ${test_tmpdir}/httpd-port 1>/dev/null; then # If so, we've successfully extracted the port break + diff -Nru flatpak-0.11.7/debian/rules flatpak-0.11.8.3/debian/rules --- flatpak-0.11.7/debian/rules 2018-03-11 16:00:02.000000000 +0000 +++ flatpak-0.11.8.3/debian/rules 2018-06-14 01:04:17.000000000 +0100 @@ -35,7 +35,6 @@ override_dh_auto_configure: dh_auto_configure -- \ - --disable-document-portal \ --enable-installed-tests \ --libexecdir=/usr/lib/flatpak \ --with-priv-mode=none \ diff -Nru flatpak-0.11.7/debian/test.sh flatpak-0.11.8.3/debian/test.sh --- flatpak-0.11.7/debian/test.sh 2018-03-11 16:00:02.000000000 +0000 +++ flatpak-0.11.8.3/debian/test.sh 2018-06-14 01:04:17.000000000 +0100 @@ -7,6 +7,11 @@ e=0 dh_auto_test || e=$? +find . -name '*.log' \ +-not -name config.log \ +-not -name test-suite.log \ +-print0 | xargs -0 tail -v -c1M + echo "Killing gpg-agent processes:" pgrep --list-full --full "gpg-agent --homedir /var/tmp/test-flatpak-.*" >&2 || : pgrep --list-full --full "gpg-agent --homedir /var/tmp/flatpak-test-.*" >&2 || : diff -Nru flatpak-0.11.7/doc/flatpak-build-commit-from.xml flatpak-0.11.8.3/doc/flatpak-build-commit-from.xml --- flatpak-0.11.7/doc/flatpak-build-commit-from.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-build-commit-from.xml 2018-05-30 13:58:57.000000000 +0100 @@ -205,16 +205,11 @@ Examples - $ flatpak build-export ~/repos/gnome-calculator/ ~/build/gnome-calculator/ org.gnome.Calculator + To revert a commit to the commit before: + + + $ flatpak build-commit-from --timestamp=NOW --src-ref=app/org.gnome.gedit/x86_64/master^ repo app/org.gnome.gedit/x86_64/master - -Commit: 9d0044ea480297114d03aec85c3d7ae3779438f9d2cb69d717fb54237acacb8c -Metadata Total: 605 -Metadata Written: 5 -Content Total: 1174 -Content Written: 1 -Content Bytes Written: 305 - diff -Nru flatpak-0.11.7/doc/flatpak-build-finish.xml flatpak-0.11.8.3/doc/flatpak-build-finish.xml --- flatpak-0.11.7/doc/flatpak-build-finish.xml 2018-04-23 13:17:07.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-build-finish.xml 2018-05-30 13:58:57.000000000 +0100 @@ -166,7 +166,7 @@ Allow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. The devel feature allows the application to @@ -178,6 +178,10 @@ natively by the system. For example, for the x86_64 architecture, 32-bit x86 binaries will be allowed as well. + + The bluetooth feature allows the application to + use bluetooth (AF_BLUETOOTH) sockets. Note, for bluetooth to + fully work you must also have network access. @@ -187,7 +191,7 @@ Disallow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. diff -Nru flatpak-0.11.7/doc/flatpak-build.xml flatpak-0.11.8.3/doc/flatpak-build.xml --- flatpak-0.11.7/doc/flatpak-build.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-build.xml 2018-05-30 13:58:57.000000000 +0100 @@ -184,18 +184,11 @@ Allow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. - - The devel feature allows the application to - access certain syscalls such as ptrace(), and - perf_event_open(). - - The multiarch feature allows the application to - execute programs compiled for an ABI other than the one supported - natively by the system. For example, for the x86_64 - architecture, 32-bit x86 binaries will be allowed as - well. + + See flatpak-build-finish1 + for the meaning of the various features. @@ -205,7 +198,7 @@ Disallow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. diff -Nru flatpak-0.11.7/doc/flatpak-metadata.xml flatpak-0.11.8.3/doc/flatpak-metadata.xml --- flatpak-0.11.7/doc/flatpak-metadata.xml 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-metadata.xml 2018-05-30 13:58:57.000000000 +0100 @@ -371,6 +371,13 @@ Available since 0.6.12. + + + Allow the application to use bluetooth (AF_BLUETOOTH) sockets. + Note, for bluetooth to fully work you must also have network access. + Available since 0.11.8. + + A feature can be prefixed with to indicate the absence of that feature, for example diff -Nru flatpak-0.11.7/doc/flatpak-override.xml flatpak-0.11.8.3/doc/flatpak-override.xml --- flatpak-0.11.7/doc/flatpak-override.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-override.xml 2018-05-30 13:58:57.000000000 +0100 @@ -174,18 +174,11 @@ Allow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. - The devel feature allows the application to - access certain syscalls such as ptrace(), and - perf_event_open(). - - The multiarch feature allows the application to - execute programs compiled for an ABI other than the one supported - natively by the system. For example, for the x86_64 - architecture, 32-bit x86 binaries will be allowed as - well. + See flatpak-build-finish1 + for the meaning of the various features. @@ -195,7 +188,7 @@ Disallow access to a specific feature. This updates the [Context] group in the metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. diff -Nru flatpak-0.11.7/doc/flatpak-remote-ls.xml flatpak-0.11.8.3/doc/flatpak-remote-ls.xml --- flatpak-0.11.7/doc/flatpak-remote-ls.xml 2018-04-20 10:45:40.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-remote-ls.xml 2018-05-30 13:58:57.000000000 +0100 @@ -131,7 +131,7 @@ Show everything. By default locale and debug extensions as well as secondary arches when the primary - arch in available are hidden. + arch is available are hidden. diff -Nru flatpak-0.11.7/doc/flatpak-run.xml flatpak-0.11.8.3/doc/flatpak-run.xml --- flatpak-0.11.7/doc/flatpak-run.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-run.xml 2018-05-30 13:58:57.000000000 +0100 @@ -225,8 +225,11 @@ Allow access to a specific feature. This overrides to the Context section from the application metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. + + See flatpak-build-finish1 + for the meaning of the various features. @@ -236,7 +239,7 @@ Disallow access to a specific feature. This overrides to the Context section from the application metadata. - FEATURE must be one of: devel, multiarch. + FEATURE must be one of: devel, multiarch, bluetooth. This option can be used multiple times. diff -Nru flatpak-0.11.7/doc/flatpak-uninstall.xml flatpak-0.11.8.3/doc/flatpak-uninstall.xml --- flatpak-0.11.7/doc/flatpak-uninstall.xml 2018-04-09 11:45:16.000000000 +0100 +++ flatpak-0.11.8.3/doc/flatpak-uninstall.xml 2018-06-11 14:52:37.000000000 +0100 @@ -138,6 +138,28 @@ + + + Remove all refs on the system. + + + + + + + Remove unused refs on the system. + + + + + + + + Automatically answer yes to all questions. This is useful for automation. + + + + diff -Nru flatpak-0.11.7/doc/Makefile.in flatpak-0.11.8.3/doc/Makefile.in --- flatpak-0.11.7/doc/Makefile.in 2018-05-03 07:26:15.000000000 +0100 +++ flatpak-0.11.8.3/doc/Makefile.in 2018-06-13 11:39:42.000000000 +0100 @@ -332,6 +332,8 @@ OSTREE_2018_5_LIBS = @OSTREE_2018_5_LIBS@ OSTREE_CFLAGS = @OSTREE_CFLAGS@ OSTREE_LIBS = @OSTREE_LIBS@ +OSTREE_P2P_REQ_CFLAGS = @OSTREE_P2P_REQ_CFLAGS@ +OSTREE_P2P_REQ_LIBS = @OSTREE_P2P_REQ_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ diff -Nru flatpak-0.11.7/doc/reference/flatpak-docs.xml flatpak-0.11.8.3/doc/reference/flatpak-docs.xml --- flatpak-0.11.7/doc/reference/flatpak-docs.xml 2018-04-03 08:42:33.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/flatpak-docs.xml 2018-05-30 13:58:57.000000000 +0100 @@ -16,11 +16,13 @@ Flatpak + + + - diff -Nru flatpak-0.11.7/doc/reference/flatpak-sections.txt flatpak-0.11.8.3/doc/reference/flatpak-sections.txt --- flatpak-0.11.7/doc/reference/flatpak-sections.txt 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/flatpak-sections.txt 2018-06-13 11:44:01.000000000 +0100 @@ -14,6 +14,7 @@ flatpak_installation_update flatpak_installation_update_full flatpak_installation_uninstall +flatpak_installation_uninstall_full flatpak_installation_launch flatpak_installation_get_current_installed_app flatpak_installation_get_display_name @@ -26,6 +27,7 @@ flatpak_installation_list_installed_refs_for_update flatpak_installation_list_installed_related_refs_sync flatpak_installation_list_remote_refs_sync +flatpak_installation_list_remotes_by_type flatpak_installation_list_remote_related_refs_sync flatpak_installation_list_remotes flatpak_installation_get_remote_by_name @@ -52,6 +54,7 @@ FlatpakProgressCallback FlatpakUpdateFlags FlatpakInstallFlags +FlatpakUninstallFlags FlatpakStorageType FLATPAK_INSTALLATION @@ -72,6 +75,8 @@ flatpak_installed_ref_get_origin flatpak_installed_ref_load_metadata flatpak_installed_ref_get_subpaths +flatpak_installed_ref_get_eol +flatpak_installed_ref_get_eol_rebase FlatpakInstalledRefClass FLATPAK_INSTALLED_REF @@ -85,6 +90,11 @@ FlatpakRemoteRef FlatpakRemoteRef flatpak_remote_ref_get_remote_name +flatpak_remote_ref_get_download_size +flatpak_remote_ref_get_eol +flatpak_remote_ref_get_eol_rebase +flatpak_remote_ref_get_installed_size +flatpak_remote_ref_get_metadata FLATPAK_IS_REMOTE_REF FLATPAK_REMOTE_REF @@ -168,6 +178,51 @@
+flatpak-transaction-progress +FlatpakTransactionProgress +FlatpakTransactionProgress +flatpak_transaction_progress_get_is_estimating +flatpak_transaction_progress_get_progress +flatpak_transaction_progress_get_status +flatpak_transaction_progress_set_update_frequency + +FlatpakTransactionProgressClass +FLATPAK_IS_TRANSACTION_PROGRESS +FLATPAK_TRANSACTION_PROGRESS +FLATPAK_TYPE_TRANSACTION_PROGRESS +flatpak_transaction_progress_get_type +
+ +
+flatpak-transaction +FlatpakTransaction +FlatpakTransaction +FlatpakTransactionOperationType +FlatpakTransactionErrorDetails +FlatpakTransactionResult +flatpak_transaction_new_for_installation +flatpak_transaction_add_install +flatpak_transaction_add_install_bundle +flatpak_transaction_add_update +flatpak_transaction_is_empty +flatpak_transaction_run + +flatpak_transaction_set_disable_dependencies +flatpak_transaction_set_disable_prune +flatpak_transaction_set_disable_related +flatpak_transaction_set_disable_static_deltas +flatpak_transaction_set_no_deploy +flatpak_transaction_set_no_pull +flatpak_transaction_set_reinstall + +FlatpakTransactionClass +FLATPAK_IS_TRANSACTION +FLATPAK_TRANSACTION +FLATPAK_TYPE_TRANSACTION +flatpak_transaction_get_type +
+ +
flatpak-version-macros FLATPAK_CHECK_VERSION FLATPAK_MAJOR_VERSION @@ -181,6 +236,9 @@ FLATPAK_ERROR FlatpakError flatpak_error_quark +FLATPAK_PORTAL_ERROR +FlatpakPortalError +flatpak_portal_error_quark
diff -Nru flatpak-0.11.7/doc/reference/flatpak.types flatpak-0.11.8.3/doc/reference/flatpak.types --- flatpak-0.11.7/doc/reference/flatpak.types 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/flatpak.types 2018-06-13 11:44:01.000000000 +0100 @@ -5,3 +5,5 @@ flatpak_related_ref_get_type flatpak_remote_get_type flatpak_remote_ref_get_type +flatpak_transaction_get_type +flatpak_transaction_progress_get_type diff -Nru flatpak-0.11.7/doc/reference/html/ch01.html flatpak-0.11.8.3/doc/reference/html/ch01.html --- flatpak-0.11.7/doc/reference/html/ch01.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/ch01.html 2018-06-13 11:44:01.000000000 +0100 @@ -27,6 +27,15 @@ FlatpakInstallation — Installation information
+FlatpakRemote — Remote repository +
+
+FlatpakTransactionProgress +
+
+FlatpakTransaction — Transaction information +
+
FlatpakRef — Application reference
@@ -39,9 +48,6 @@ FlatpakRemoteRef — Remote application reference
-FlatpakRemote — Remote repository -
-
flatpak-bundle-ref
diff -Nru flatpak-0.11.7/doc/reference/html/flatpak.devhelp2 flatpak-0.11.8.3/doc/reference/html/flatpak.devhelp2 --- flatpak-0.11.7/doc/reference/html/flatpak.devhelp2 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/flatpak.devhelp2 2018-06-13 11:44:01.000000000 +0100 @@ -3,11 +3,13 @@ + + + - @@ -29,6 +31,7 @@ + @@ -41,6 +44,7 @@ + @@ -68,7 +72,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -92,6 +154,8 @@ + + @@ -106,10 +170,16 @@ + + + + + + @@ -117,34 +187,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -156,8 +198,11 @@ + + + @@ -167,22 +212,42 @@ + + + - - + + + + + + + + + + + + + + + + + + + diff -Nru flatpak-0.11.7/doc/reference/html/flatpak-Error-codes.html flatpak-0.11.8.3/doc/reference/html/flatpak-Error-codes.html --- flatpak-0.11.7/doc/reference/html/flatpak-Error-codes.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/flatpak-Error-codes.html 2018-06-13 11:44:01.000000000 +0100 @@ -38,14 +38,24 @@ - + + GQuark flatpak_error_quark () - + + + +GQuark + + +flatpak_portal_error_quark () + + +
@@ -64,6 +74,14 @@ enum FlatpakError + +#define +FLATPAK_PORTAL_ERROR + + +enum +FlatpakPortalError +
@@ -77,6 +95,12 @@
GQuark
 flatpak_error_quark (void);
+
+
+

flatpak_portal_error_quark ()

+
GQuark
+flatpak_portal_error_quark (void);
+

Types and Values

@@ -120,6 +144,105 @@   + +

FLATPAK_ERROR_DIFFERENT_REMOTE

+ +

The App/Runtime is already installed, but from a different remote.

+ +  + + +

FLATPAK_ERROR_ABORTED

+ +

The transaction was aborted (returned TRUE in operation-error signal).

+ +  + + +

FLATPAK_ERROR_SKIPPED

+ +

The App/Runtime install was skipped due to earlier errors.

+ +  + + +

FLATPAK_ERROR_NEED_NEW_FLATPAK

+ +

The App/Runtime needs a more recent version of flatpak.

+ +  + + +
+ + +
+
+

FLATPAK_PORTAL_ERROR

+
#define FLATPAK_PORTAL_ERROR flatpak_portal_error_quark ()
+
+
+
+
+

enum FlatpakPortalError

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

FLATPAK_PORTAL_ERROR_FAILED

+

General portal failure

+
 

FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT

+

An argument was invalid

+
 

FLATPAK_PORTAL_ERROR_NOT_FOUND

+

The object was not fount

+
 

FLATPAK_PORTAL_ERROR_EXISTS

+

The object already exists

+
 

FLATPAK_PORTAL_ERROR_NOT_ALLOWED

+

The call was not allowed

+
 

FLATPAK_PORTAL_ERROR_CANCELLED

+

The call was cancelled by the user

+
 

FLATPAK_PORTAL_ERROR_WINDOW_DESTROYED

+

The window was destroyed by the user

+
 
diff -Nru flatpak-0.11.7/doc/reference/html/flatpak-flatpak-bundle-ref.html flatpak-0.11.8.3/doc/reference/html/flatpak-flatpak-bundle-ref.html --- flatpak-0.11.7/doc/reference/html/flatpak-flatpak-bundle-ref.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/flatpak-flatpak-bundle-ref.html 2018-06-13 11:44:01.000000000 +0100 @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@ Home Up -Prev +Prev Next
diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakInstallation.html flatpak-0.11.8.3/doc/reference/html/FlatpakInstallation.html --- flatpak-0.11.7/doc/reference/html/FlatpakInstallation.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakInstallation.html 2018-06-13 11:44:01.000000000 +0100 @@ -7,7 +7,7 @@ - + @@ -21,7 +21,7 @@ Home Up Prev -Next +Next
@@ -141,6 +141,14 @@ gboolean +flatpak_installation_uninstall_full () + + + + +gboolean + + flatpak_installation_launch () @@ -235,6 +243,14 @@ GPtrArray * +flatpak_installation_list_remotes_by_type () + + + + +GPtrArray * + + flatpak_installation_list_remote_related_refs_sync () @@ -445,6 +461,10 @@ enum +FlatpakUninstallFlags + + +enum FlatpakStorageType @@ -465,7 +485,7 @@ system-wide (in $prefix/var/lib/flatpak) or per-user (in ~/.local/share/flatpak).

FlatpakInstallation can list configured remotes as well as installed application and runtime references (in short: refs). It can also run, install, update and -uninstall applications and runtimes.

+uninstall applications and runtimes, using FlatpakTransaction.

Functions

@@ -1183,6 +1203,90 @@

+

flatpak_installation_uninstall_full ()

+
gboolean
+flatpak_installation_uninstall_full (FlatpakInstallation *self,
+                                     FlatpakUninstallFlags flags,
+                                     FlatpakRefKind kind,
+                                     const char *name,
+                                     const char *arch,
+                                     const char *branch,
+                                     FlatpakProgressCallback progress,
+                                     gpointer progress_data,
+                                     GCancellable *cancellable,
+                                     GError **error);
+

Uninstall an application or runtime.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

a FlatpakInstallation

 

flags

set of FlatpakUninstallFlags flags

 

kind

what this ref contains (an FlatpakRefKind)

 

name

name of the app or runtime to uninstall

 

arch

architecture of the app or runtime to uninstall

 

branch

name of the branch of the app or runtime to uninstall

 

progress

the callback.

[scope call][nullable]

progress_data

user data passed to progress +.

[closure progress][nullable]

cancellable

a GCancellable.

[nullable]

error

return location for a GError

 
+
+
+

Returns

+

TRUE on success

+
+

Since: 0.11.8

+
+
+

flatpak_installation_launch ()

gboolean
 flatpak_installation_launch (FlatpakInstallation *self,
@@ -1738,6 +1842,63 @@
 

+

flatpak_installation_list_remotes_by_type ()

+
GPtrArray *
+flatpak_installation_list_remotes_by_type
+                               (FlatpakInstallation *self,
+                                const FlatpakRemoteType types[],
+                                gsize num_types,
+                                GCancellable *cancellable,
+                                GError **error);
+

Lists only the remotes whose type is included in the types + argument.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

a FlatpakInstallation

 

types

an array of FlatpakRemoteType.

[array length=num_types]

num_types

the number of types provided in types +

 

cancellable

a GCancellable.

[nullable]

error

return location for a GError

 
+
+
+

Returns

+

a GPtrArray of +FlatpakRemote instances.

+

[transfer container][element-type FlatpakRemote]

+
+
+
+

flatpak_installation_list_remote_related_refs_sync ()

GPtrArray *
 flatpak_installation_list_remote_related_refs_sync
@@ -1759,6 +1920,8 @@
 reference should be installed/updated with the app, and
 flatpak_related_ref_should_delete() returns TRUE if it
 should be uninstalled with the main ref.

+

The commit property of each FlatpakRelatedRef is not guaranteed to be +non-NULL.

Parameters

@@ -2989,8 +3152,17 @@ - - + + + + + + +

FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS

   +

Don't use static deltas when pulling

+
 

FLATPAK_UPDATE_FLAGS_NO_PRUNE

+

Don't prune the local OSTree repository after updating (Since: 0.11.8)

+
 
@@ -3018,22 +3190,60 @@

FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS

-  -  + +

Don't use static deltas when pulling

+ + 

FLATPAK_INSTALL_FLAGS_NO_DEPLOY

-  -  + +

Don't install any new builds that might be fetched

+ + 

FLATPAK_INSTALL_FLAGS_NO_PULL

-  -  + +

Don't try to fetch new builds from the remote repo

+ +  + + +
+
+
+
+
+

enum FlatpakUninstallFlags

+

Flags to alter the behavior of flatpak_installation_uninstall_full().

+
+

Members

+
+++++ + + + + + + + + + +

FLATPAK_UNINSTALL_FLAGS_NONE

+

Default

+
 

FLATPAK_UNINSTALL_FLAGS_NO_PRUNE

+

Don't prune the local OSTree repository after uninstalling

+
 
+

Since: 0.11.8


diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakInstalledRef.html flatpak-0.11.8.3/doc/reference/html/FlatpakInstalledRef.html --- flatpak-0.11.7/doc/reference/html/FlatpakInstalledRef.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakInstalledRef.html 2018-06-13 11:44:01.000000000 +0100 @@ -93,6 +93,20 @@ flatpak_installed_ref_get_subpaths () + +const char * + + +flatpak_installed_ref_get_eol () + + + +const char * + + +flatpak_installed_ref_get_eol_rebase () + +
@@ -384,6 +398,62 @@

[transfer none]

+
+
+

flatpak_installed_ref_get_eol ()

+
const char *
+flatpak_installed_ref_get_eol (FlatpakInstalledRef *self);
+

Returns the end-of-life reason string, or NULL if the +ref is not end-of-lifed.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakInstalledRef

 
+
+
+

Returns

+

the end-of-life reason or NULL.

+

[transfer none]

+
+
+
+
+

flatpak_installed_ref_get_eol_rebase ()

+
const char *
+flatpak_installed_ref_get_eol_rebase (FlatpakInstalledRef *self);
+

Returns the end-of-life rebased ref, or NULL if the +ref is not end-of-lifed.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakInstalledRef

 
+
+
+

Returns

+

the end-of-life rebased ref or NULL.

+

[transfer none]

+
+

Types and Values

diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakRef.html flatpak-0.11.8.3/doc/reference/html/FlatpakRef.html --- flatpak-0.11.7/doc/reference/html/FlatpakRef.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakRef.html 2018-06-13 11:44:01.000000000 +0100 @@ -6,7 +6,7 @@ - + @@ -21,7 +21,7 @@ Home Up -Prev +Prev Next
diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakRelatedRef.html flatpak-0.11.8.3/doc/reference/html/FlatpakRelatedRef.html --- flatpak-0.11.7/doc/reference/html/FlatpakRelatedRef.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakRelatedRef.html 2018-06-13 11:44:01.000000000 +0100 @@ -86,6 +86,11 @@ gboolean +should-autoprune +Read / Write / Construct Only + + +gboolean should-delete Read / Write / Construct Only @@ -212,6 +217,14 @@

Property Details

+

The “should-autoprune” property

+
  “should-autoprune”         gboolean
+

Whether to delete when pruning unused refs.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+

The “should-delete” property

  “should-delete”            gboolean

Whether to auto-delete the ref with the main ref.

diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakRemote.html flatpak-0.11.8.3/doc/reference/html/FlatpakRemote.html --- flatpak-0.11.7/doc/reference/html/FlatpakRemote.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakRemote.html 2018-06-13 11:44:01.000000000 +0100 @@ -6,8 +6,8 @@ - - + + @@ -21,8 +21,8 @@ Home Up -Prev -Next +Prev +Next
@@ -990,7 +990,7 @@

Returns

-

whether the remote is marked as "don't enumerate"

+

whether the remote is marked as disabled


@@ -1036,6 +1036,8 @@

enum FlatpakRemoteType

+

Different types of FlatpakRemote +.

Members

@@ -1047,18 +1049,24 @@ - - + + - - + + - - + +

FLATPAK_REMOTE_TYPE_STATIC

   +

Statically configured remote

+
 

FLATPAK_REMOTE_TYPE_USB

   +

Dynamically detected local pathname remote

+
 

FLATPAK_REMOTE_TYPE_LAN

   +

Dynamically detected network remote

+
 
diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakRemoteRef.html flatpak-0.11.8.3/doc/reference/html/FlatpakRemoteRef.html --- flatpak-0.11.7/doc/reference/html/FlatpakRemoteRef.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakRemoteRef.html 2018-06-13 11:44:01.000000000 +0100 @@ -7,7 +7,7 @@ - + @@ -22,7 +22,7 @@ Home Up Prev -Next +Next
@@ -40,13 +40,53 @@ - + + const char * flatpak_remote_ref_get_remote_name () - + + + +guint64 + + +flatpak_remote_ref_get_download_size () + + + +const char * + + +flatpak_remote_ref_get_eol () + + + +const char * + + +flatpak_remote_ref_get_eol_rebase () + + + + +guint64 + + +flatpak_remote_ref_get_installed_size () + + + + +GBytes * + + +flatpak_remote_ref_get_metadata () + + +
@@ -148,6 +188,142 @@

[transfer none]

+
+
+

flatpak_remote_ref_get_download_size ()

+
guint64
+flatpak_remote_ref_get_download_size (FlatpakRemoteRef *self);
+

Returns the download size of the ref.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakRemoteRef

 
+
+
+

Returns

+

the download size

+
+
+
+
+

flatpak_remote_ref_get_eol ()

+
const char *
+flatpak_remote_ref_get_eol (FlatpakRemoteRef *self);
+

Returns the end-of-life reason string, or NULL if the +ref is not end-of-lifed.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakRemoteRef

 
+
+
+

Returns

+

the end-of-life reason or NULL.

+

[transfer none]

+
+
+
+
+

flatpak_remote_ref_get_eol_rebase ()

+
const char *
+flatpak_remote_ref_get_eol_rebase (FlatpakRemoteRef *self);
+

Returns the end-of-life rebased ref, or NULL if the +ref is not end-of-lifed.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakRemoteRef

 
+
+
+

Returns

+

the end-of-life rebased ref or NULL.

+

[transfer none]

+
+
+
+
+

flatpak_remote_ref_get_installed_size ()

+
guint64
+flatpak_remote_ref_get_installed_size (FlatpakRemoteRef *self);
+

Returns the installed size of the ref.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakRemoteRef

 
+
+
+

Returns

+

the installed size

+
+
+
+
+

flatpak_remote_ref_get_metadata ()

+
GBytes *
+flatpak_remote_ref_get_metadata (FlatpakRemoteRef *self);
+

Returns the app metadata from the metadata cach of the ref.

+
+

Parameters

+
+++++ + + + + + +

self

a FlatpakRemoteRef

 
+
+
+

Returns

+

a GBytes with the metadata file +contents or NULL.

+

[transfer none][nullable]

+
+

Types and Values

diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakTransaction.html flatpak-0.11.8.3/doc/reference/html/FlatpakTransaction.html --- flatpak-0.11.7/doc/reference/html/FlatpakTransaction.html 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakTransaction.html 2018-06-13 11:44:01.000000000 +0100 @@ -0,0 +1,794 @@ + + + + +FlatpakTransaction: Flatpak Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

FlatpakTransaction

+

FlatpakTransaction — Transaction information

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+FlatpakTransaction * + +flatpak_transaction_new_for_installation () +
+gboolean + +flatpak_transaction_add_install () +
+gboolean + +flatpak_transaction_add_install_bundle () +
+gboolean + +flatpak_transaction_add_update () +
+gboolean + +flatpak_transaction_is_empty () +
+gboolean + +flatpak_transaction_run () +
+void + +flatpak_transaction_set_disable_dependencies () +
+void + +flatpak_transaction_set_disable_prune () +
+void + +flatpak_transaction_set_disable_related () +
+void + +flatpak_transaction_set_disable_static_deltas () +
+void + +flatpak_transaction_set_no_deploy () +
+void + +flatpak_transaction_set_no_pull () +
+void + +flatpak_transaction_set_reinstall () +
+
+
+

Properties

+
+++++ + + + + + +
+FlatpakInstallation *installationRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gintchoose-remote-for-refRun Last
voidend-of-lifedRun Last
voidnew-operationRun Last
voidoperation-doneRun Last
gbooleanoperation-errorRun Last
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── FlatpakTransaction
+
+
+
+

Implemented Interfaces

+

+FlatpakTransaction implements + GInitable.

+
+
+

Description

+

FlatpakTransaction is an object representing an install/update +transaction. You create an object like this using flatpak_transaction_new_for_installation() +and then you add all the operations (installs, updates, etc) you wish to do. Then +you start the transaction with flatpak_transaction_run() which will resolve all kinds +of dependencies and report progress and status while downloading and installing these.

+

A transaction is a blocking operation, and all signals are emitted in the same thread. +This means you should either handle the signals directly (say, by doing blocking console +interaction, or by just returning without interaction), or run the operation in a separate +thread and do your own forwarding to the GUI thread.

+
+
+

Functions

+
+

flatpak_transaction_new_for_installation ()

+
FlatpakTransaction *
+flatpak_transaction_new_for_installation
+                               (FlatpakInstallation *installation,
+                                GCancellable *cancellable,
+                                GError **error);
+

Creates a new FlatpakTransaction object that can be used to do installation +and updates of multiple refs, as well as their dependencies, in a single +operation. Set the options you want on the transaction and add the +refs you want to install/update, then start the transaction with +flatpak_transaction_run().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

installation

a FlatpakInstallation

 

cancellable

a GCancellable.

[nullable]

error

return location for a GError

 
+
+
+

Returns

+

a FlatpakTransaction, or NULL on failure.

+

[transfer full]

+
+
+
+
+

flatpak_transaction_add_install ()

+
gboolean
+flatpak_transaction_add_install (FlatpakTransaction *self,
+                                 const char *remote,
+                                 const char *ref,
+                                 const char **subpaths,
+                                 GError **error);
+
+
+
+

flatpak_transaction_add_install_bundle ()

+
gboolean
+flatpak_transaction_add_install_bundle
+                               (FlatpakTransaction *self,
+                                GFile *file,
+                                GBytes *gpg_data,
+                                GError **error);
+
+
+
+

flatpak_transaction_add_update ()

+
gboolean
+flatpak_transaction_add_update (FlatpakTransaction *self,
+                                const char *ref,
+                                const char **subpaths,
+                                const char *commit,
+                                GError **error);
+
+
+
+

flatpak_transaction_is_empty ()

+
gboolean
+flatpak_transaction_is_empty (FlatpakTransaction *self);
+
+
+
+

flatpak_transaction_run ()

+
gboolean
+flatpak_transaction_run (FlatpakTransaction *self,
+                         GCancellable *cancellable,
+                         GError **error);
+
+
+
+

flatpak_transaction_set_disable_dependencies ()

+
void
+flatpak_transaction_set_disable_dependencies
+                               (FlatpakTransaction *self,
+                                gboolean disable_dependencies);
+
+
+
+

flatpak_transaction_set_disable_prune ()

+
void
+flatpak_transaction_set_disable_prune (FlatpakTransaction *self,
+                                       gboolean disable_prune);
+
+
+
+

flatpak_transaction_set_disable_related ()

+
void
+flatpak_transaction_set_disable_related
+                               (FlatpakTransaction *self,
+                                gboolean disable_related);
+
+
+
+

flatpak_transaction_set_disable_static_deltas ()

+
void
+flatpak_transaction_set_disable_static_deltas
+                               (FlatpakTransaction *self,
+                                gboolean disable_static_deltas);
+
+
+
+

flatpak_transaction_set_no_deploy ()

+
void
+flatpak_transaction_set_no_deploy (FlatpakTransaction *self,
+                                   gboolean no_deploy);
+
+
+
+

flatpak_transaction_set_no_pull ()

+
void
+flatpak_transaction_set_no_pull (FlatpakTransaction *self,
+                                 gboolean no_pull);
+
+
+
+

flatpak_transaction_set_reinstall ()

+
void
+flatpak_transaction_set_reinstall (FlatpakTransaction *self,
+                                   gboolean reinstall);
+
+
+
+

Types and Values

+
+

FlatpakTransaction

+
typedef struct _FlatpakTransaction FlatpakTransaction;
+
+
+
+

enum FlatpakTransactionOperationType

+

The type of a transaction, used in FlatpakTransaction::new-operation

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

FLATPAK_TRANSACTION_OPERATION_INSTALL

+

Install a ref from a remote

+
 

FLATPAK_TRANSACTION_OPERATION_UPDATE

+

Update an installed ref

+
 

FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE

+

Install a bundle from a file

+
 

FLATPAK_TRANSACTION_OPERATION_UNINSTALL

+

Uninstall a ref

+
 
+
+
+
+
+

enum FlatpakTransactionErrorDetails

+

The details for FlatpakTransaction::operation-error

+
+

Members

+
+++++ + + + + + +

FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL

+

The operation failure was not fatal

+
 
+
+
+
+
+

enum FlatpakTransactionResult

+
+

Members

+
+++++ + + + + + +

FLATPAK_TRANSACTION_RESULT_NO_CHANGE

+

The update caused no changes

+
 
+
+
+
+
+

Property Details

+
+

The “installation” property

+
  “installation”             FlatpakInstallation *
+

The installation instance.

+

Flags: Read / Write / Construct Only

+
+
+
+

Signal Details

+
+

The “choose-remote-for-ref” signal

+
gint
+user_function (FlatpakTransaction *object,
+               gchar              *for_ref,
+               gchar              *runtime_ref,
+               GStrv               remotes,
+               gpointer            user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

A FlatpakTransaction

 

for_ref

The ref we are installing

 

runtime_ref

The ref we are looking for

 

remotes

the remotes that has the ref, sorted in prio order

 

user_data

user data set when the signal handler was connected.

 
+
+
+

Returns

+

the index of the remote to use, or -1 to not pick one (and fail)

+
+

Flags: Run Last

+
+
+
+

The “end-of-lifed” signal

+
void
+user_function (FlatpakTransaction *object,
+               gchar              *ref,
+               gchar              *reason,
+               gchar              *rebase,
+               gpointer            user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

A FlatpakTransaction

 

ref

The ref we are installing

 

reason

The eol reason, or NULL

 

rebase

The new name, if rebased, or NULL

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “new-operation” signal

+
void
+user_function (FlatpakTransaction         *object,
+               gchar                      *ref,
+               gchar                      *remote,
+               gchar                      *bundle,
+               gint                        operation_type,
+               FlatpakTransactionProgress *progress,
+               gpointer                    user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

A FlatpakTransaction

 

ref

The ref the operation will be working on

 

remote

The ref the operation will be working on

 

bundle

The bundle path (or NULL)

 

operation_type

A FlatpakTransactionOperationType specifying operation type

 

progress

A FlatpakTransactionProgress

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “operation-done” signal

+
void
+user_function (FlatpakTransaction *object,
+               gchar              *ref,
+               gchar              *remote,
+               gint                operation_type,
+               gchar              *commit,
+               gpointer            user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

A FlatpakTransaction

 

ref

The ref the operation was working on

 

remote

The remote

 

operation_type

A FlatpakTransactionOperationType specifying operation type

 

commit

The new commit checksum

 

result

A FlatpakTransactionResult giving details about the result

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “operation-error” signal

+
gboolean
+user_function (FlatpakTransaction *object,
+               gchar              *ref,
+               gchar              *remote,
+               gint                operation_type,
+               GError             *error,
+               gint                details,
+               gpointer            user_data)
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

A FlatpakTransaction

 

ref

The ref the operation was working on

 

remote

The remote

 

operation_type

A FlatpakTransactionOperationType specifying operation type

 

error

A GError

 

details

A FlatpakTransactionErrorDetails with Details about the error

 

user_data

user data set when the signal handler was connected.

 
+
+
+

Returns

+

the TRUE to contine transaction, FALSE to stop

+
+

Flags: Run Last

+
+
+
+ + + \ No newline at end of file diff -Nru flatpak-0.11.7/doc/reference/html/FlatpakTransactionProgress.html flatpak-0.11.8.3/doc/reference/html/FlatpakTransactionProgress.html --- flatpak-0.11.7/doc/reference/html/FlatpakTransactionProgress.html 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/FlatpakTransactionProgress.html 2018-06-13 11:44:01.000000000 +0100 @@ -0,0 +1,191 @@ + + + + +FlatpakTransactionProgress: Flatpak Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

FlatpakTransactionProgress

+

FlatpakTransactionProgress

+
+
+

Functions

+ +
+
+

Signals

+
+++++ + + + + + +
voidchangedRun Last
+
+
+

Types and Values

+
++++ + + + + +
 FlatpakTransactionProgress
+
+
+

Object Hierarchy

+
    GObject
+    ╰── FlatpakTransactionProgress
+
+
+
+

Description

+
+
+

Functions

+
+

flatpak_transaction_progress_get_is_estimating ()

+
gboolean
+flatpak_transaction_progress_get_is_estimating
+                               (FlatpakTransactionProgress *self);
+
+
+
+

flatpak_transaction_progress_get_progress ()

+
int
+flatpak_transaction_progress_get_progress
+                               (FlatpakTransactionProgress *self);
+
+
+
+

flatpak_transaction_progress_get_status ()

+
char *
+flatpak_transaction_progress_get_status
+                               (FlatpakTransactionProgress *self);
+
+
+
+

flatpak_transaction_progress_set_update_frequency ()

+
void
+flatpak_transaction_progress_set_update_frequency
+                               (FlatpakTransactionProgress *self,
+                                guint update_frequency);
+
+
+
+

Types and Values

+
+

FlatpakTransactionProgress

+
typedef struct _FlatpakTransactionProgress FlatpakTransactionProgress;
+
+
+
+

Signal Details

+
+

The “changed” signal

+
void
+user_function (FlatpakTransactionProgress *object,
+               gpointer                    user_data)
+

Emitted when some detail of the progress object changes, you can call the various methods to get the current status.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

A FlatpakTransactionProgress

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+ + + \ No newline at end of file diff -Nru flatpak-0.11.7/doc/reference/html/flatpak-Version-information.html flatpak-0.11.8.3/doc/reference/html/flatpak-Version-information.html --- flatpak-0.11.7/doc/reference/html/flatpak-Version-information.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/flatpak-Version-information.html 2018-06-13 11:44:01.000000000 +0100 @@ -99,7 +99,7 @@

FLATPAK_MICRO_VERSION

-
#define FLATPAK_MICRO_VERSION (7)
+
#define FLATPAK_MICRO_VERSION (8)
 

diff -Nru flatpak-0.11.7/doc/reference/html/full-api-index.html flatpak-0.11.8.3/doc/reference/html/full-api-index.html --- flatpak-0.11.7/doc/reference/html/full-api-index.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/full-api-index.html 2018-06-13 11:44:01.000000000 +0100 @@ -31,6 +31,8 @@  |  S  |  + T +  |  U Home @@ -226,6 +228,10 @@
+flatpak_installation_list_remotes_by_type, function in FlatpakInstallation +
+
+
flatpak_installation_list_remote_refs_sync, function in FlatpakInstallation
@@ -278,6 +284,10 @@
+flatpak_installation_uninstall_full, function in FlatpakInstallation +
+
+
flatpak_installation_update, function in FlatpakInstallation
@@ -338,6 +348,14 @@
+flatpak_installed_ref_get_eol, function in FlatpakInstalledRef +
+
+
+flatpak_installed_ref_get_eol_rebase, function in FlatpakInstalledRef +
+
+
flatpak_installed_ref_get_installed_size, function in FlatpakInstalledRef
@@ -380,6 +398,18 @@

P

+FlatpakPortalError, enum in Error codes +
+
+
+FLATPAK_PORTAL_ERROR, macro in Error codes +
+
+
+flatpak_portal_error_quark, function in Error codes +
+
+
FlatpakProgressCallback, user_function in FlatpakInstallation
@@ -453,6 +483,10 @@
+FlatpakRelatedRef:should-autoprune, object property in FlatpakRelatedRef +
+
+
FlatpakRelatedRef:should-delete, object property in FlatpakRelatedRef
@@ -581,6 +615,26 @@
+flatpak_remote_ref_get_download_size, function in FlatpakRemoteRef +
+
+
+flatpak_remote_ref_get_eol, function in FlatpakRemoteRef +
+
+
+flatpak_remote_ref_get_eol_rebase, function in FlatpakRemoteRef +
+
+
+flatpak_remote_ref_get_installed_size, function in FlatpakRemoteRef +
+
+
+flatpak_remote_ref_get_metadata, function in FlatpakRemoteRef +
+
+
flatpak_remote_ref_get_remote_name, function in FlatpakRemoteRef
@@ -629,8 +683,129 @@ FlatpakStorageType, enum in FlatpakInstallation
+

T

+
+FlatpakTransaction, struct in FlatpakTransaction +
+
+
+FlatpakTransaction::choose-remote-for-ref, object signal in FlatpakTransaction +
+
+
+FlatpakTransaction::end-of-lifed, object signal in FlatpakTransaction +
+
+
+FlatpakTransaction::new-operation, object signal in FlatpakTransaction +
+
+
+FlatpakTransaction::operation-done, object signal in FlatpakTransaction +
+
+
+FlatpakTransaction::operation-error, object signal in FlatpakTransaction +
+
+
+FlatpakTransaction:installation, object property in FlatpakTransaction +
+
+
+FlatpakTransactionErrorDetails, enum in FlatpakTransaction +
+
+
+FlatpakTransactionOperationType, enum in FlatpakTransaction +
+
+
+FlatpakTransactionProgress, struct in FlatpakTransactionProgress +
+
+
+FlatpakTransactionProgress::changed, object signal in FlatpakTransactionProgress +
+
+
+FlatpakTransactionResult, enum in FlatpakTransaction +
+
+
+flatpak_transaction_add_install, function in FlatpakTransaction +
+
+
+flatpak_transaction_add_install_bundle, function in FlatpakTransaction +
+
+
+flatpak_transaction_add_update, function in FlatpakTransaction +
+
+
+flatpak_transaction_is_empty, function in FlatpakTransaction +
+
+
+flatpak_transaction_new_for_installation, function in FlatpakTransaction +
+
+
+flatpak_transaction_progress_get_is_estimating, function in FlatpakTransactionProgress +
+
+
+flatpak_transaction_progress_get_progress, function in FlatpakTransactionProgress +
+
+
+flatpak_transaction_progress_get_status, function in FlatpakTransactionProgress +
+
+
+flatpak_transaction_progress_set_update_frequency, function in FlatpakTransactionProgress +
+
+
+flatpak_transaction_run, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_disable_dependencies, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_disable_prune, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_disable_related, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_disable_static_deltas, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_no_deploy, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_no_pull, function in FlatpakTransaction +
+
+
+flatpak_transaction_set_reinstall, function in FlatpakTransaction +
+

U

+FlatpakUninstallFlags, enum in FlatpakInstallation +
+
+
FlatpakUpdateFlags, enum in FlatpakInstallation
diff -Nru flatpak-0.11.7/doc/reference/html/index.html flatpak-0.11.8.3/doc/reference/html/index.html --- flatpak-0.11.7/doc/reference/html/index.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/index.html 2018-06-13 11:44:01.000000000 +0100 @@ -15,7 +15,7 @@

- For flatpak 0.11.7 + For flatpak 0.11.8

@@ -28,6 +28,15 @@ FlatpakInstallation — Installation information
+FlatpakRemote — Remote repository +
+
+FlatpakTransactionProgress +
+
+FlatpakTransaction — Transaction information +
+
FlatpakRef — Application reference
@@ -40,9 +49,6 @@ FlatpakRemoteRef — Remote application reference
-FlatpakRemote — Remote repository -
-
flatpak-bundle-ref
diff -Nru flatpak-0.11.7/doc/reference/html/object-tree.html flatpak-0.11.8.3/doc/reference/html/object-tree.html --- flatpak-0.11.7/doc/reference/html/object-tree.html 2018-05-03 07:26:54.000000000 +0100 +++ flatpak-0.11.8.3/doc/reference/html/object-tree.html 2018-06-13 11:44:01.000000000 +0100 @@ -30,7 +30,9 @@ ├── FlatpakRelatedRef ╰── FlatpakRemoteRef ├── FlatpakInstallation - ╰── FlatpakRemote + ├── FlatpakRemote + ├── FlatpakTransaction + ╰── FlatpakTransactionProgress