summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/flatpak-dir.c162
-rw-r--r--common/flatpak-dir.h6
-rw-r--r--data/org.freedesktop.Flatpak.xml6
-rw-r--r--system-helper/flatpak-system-helper.c92
-rw-r--r--system-helper/org.freedesktop.Flatpak.policy.in18
5 files changed, 244 insertions, 40 deletions
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 4d41e04..9899618 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -39,6 +39,10 @@
#define NO_SYSTEM_HELPER ((FlatpakSystemHelper *) (gpointer) 1)
+static OstreeRepo * flatpak_dir_create_system_child_repo (FlatpakDir *self,
+ GLnxLockFile *file_lock,
+ GError **error);
+
struct FlatpakDir
{
GObject parent;
@@ -936,63 +940,36 @@ flatpak_dir_remove_all_refs (FlatpakDir *self,
}
gboolean
-flatpak_dir_update_appstream (FlatpakDir *self,
+flatpak_dir_deploy_appstream (FlatpakDir *self,
const char *remote,
const char *arch,
gboolean *out_changed,
- OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error)
{
- g_autofree char *branch = NULL;
- g_autofree char *remote_and_branch = NULL;
- g_autofree char *old_checksum = NULL;
- g_autofree char *new_checksum = NULL;
-
- g_autoptr(GFile) root = NULL;
g_autoptr(GFile) appstream_dir = NULL;
g_autoptr(GFile) remote_dir = NULL;
g_autoptr(GFile) arch_dir = NULL;
g_autoptr(GFile) checkout_dir = NULL;
- g_autoptr(GFile) old_checkout_dir = NULL;
- g_autoptr(GFileInfo) file_info = NULL;
+ g_autoptr(GFile) timestamp_file = NULL;
g_autofree char *arch_path = NULL;
+ gboolean checkout_exists;
+ g_autofree char *remote_and_branch = NULL;
+ const char *old_checksum = NULL;
+ g_autofree char *new_checksum = NULL;
+ g_autoptr(GFile) active_link = NULL;
+ g_autoptr(GFileInfo) file_info = NULL;
+ g_autofree char *branch = NULL;
+ g_autoptr(GFile) root = NULL;
+ g_autoptr(GFile) old_checkout_dir = NULL;
g_autofree char *tmpname = NULL;
g_autoptr(GFile) active_tmp_link = NULL;
- g_autoptr(GFile) active_link = NULL;
- g_autoptr(GFile) timestamp_file = NULL;
g_autoptr(GError) tmp_error = NULL;
- gboolean checkout_exists;
-
- if (!flatpak_dir_ensure_repo (self, cancellable, error))
- return FALSE;
-
- if (arch == NULL)
- arch = flatpak_get_arch ();
-
- branch = g_strdup_printf ("appstream/%s", arch);
- remote_and_branch = g_strdup_printf ("%s:%s", remote, branch);
-
- if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, &old_checksum, error))
- return FALSE;
-
- if (!flatpak_dir_pull (self, remote, branch, NULL, NULL, OSTREE_REPO_PULL_FLAGS_NONE, progress,
- cancellable, error))
- return FALSE;
-
- if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, &new_checksum, error))
- return FALSE;
-
- if (new_checksum == NULL)
- {
- g_warning ("No appstream branch in remote %s\n", remote);
- return TRUE;
- }
appstream_dir = g_file_get_child (flatpak_dir_get_path (self), "appstream");
remote_dir = g_file_get_child (appstream_dir, remote);
arch_dir = g_file_get_child (remote_dir, arch);
- checkout_dir = g_file_get_child (arch_dir, new_checksum);
+ active_link = g_file_get_child (arch_dir, "active");
timestamp_file = g_file_get_child (arch_dir, ".timestamp");
arch_path = g_file_get_path (arch_dir);
@@ -1002,6 +979,20 @@ flatpak_dir_update_appstream (FlatpakDir *self,
return FALSE;
}
+ old_checksum = NULL;
+ file_info = g_file_query_info (active_link, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, NULL);
+ if (file_info != NULL)
+ old_checksum = g_file_info_get_symlink_target (file_info);
+
+ branch = g_strdup_printf ("appstream/%s", arch);
+ remote_and_branch = g_strdup_printf ("%s:%s", remote, branch);
+
+ if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, &new_checksum, error))
+ return FALSE;
+
+ checkout_dir = g_file_get_child (arch_dir, new_checksum);
checkout_exists = g_file_query_exists (checkout_dir, NULL);
if (old_checksum != NULL && new_checksum != NULL &&
@@ -1036,7 +1027,6 @@ flatpak_dir_update_appstream (FlatpakDir *self,
tmpname = gs_fileutil_gen_tmp_name (".active-", NULL);
active_tmp_link = g_file_get_child (arch_dir, tmpname);
- active_link = g_file_get_child (arch_dir, "active");
if (!g_file_make_symbolic_link (active_tmp_link, new_checksum, cancellable, error))
return FALSE;
@@ -1068,9 +1058,101 @@ flatpak_dir_update_appstream (FlatpakDir *self,
if (out_changed)
*out_changed = TRUE;
+
return TRUE;
}
+gboolean
+flatpak_dir_update_appstream (FlatpakDir *self,
+ const char *remote,
+ const char *arch,
+ gboolean *out_changed,
+ OstreeAsyncProgress *progress,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree char *branch = NULL;
+ g_autofree char *remote_and_branch = NULL;
+ g_autofree char *new_checksum = NULL;
+
+ if (out_changed)
+ *out_changed = FALSE;
+
+ if (arch == NULL)
+ arch = flatpak_get_arch ();
+
+ branch = g_strdup_printf ("appstream/%s", arch);
+
+ if (!flatpak_dir_ensure_repo (self, cancellable, error))
+ return FALSE;
+
+ if (flatpak_dir_use_child_repo (self))
+ {
+ g_autoptr(OstreeRepo) child_repo = NULL;
+ g_auto(GLnxLockFile) child_repo_lock = GLNX_LOCK_FILE_INIT;
+ FlatpakSystemHelper *system_helper;
+
+ child_repo = flatpak_dir_create_system_child_repo (self, &child_repo_lock, error);
+ if (child_repo == NULL)
+ return FALSE;
+
+ system_helper = flatpak_dir_get_system_helper (self);
+
+ g_assert (system_helper != NULL);
+
+ if (!flatpak_dir_pull (self, remote, branch, NULL,
+ child_repo, OSTREE_REPO_PULL_FLAGS_MIRROR,
+ progress, cancellable, error))
+ return FALSE;
+
+ if (!ostree_repo_resolve_rev (child_repo, branch, TRUE, &new_checksum, error))
+ return FALSE;
+
+ if (new_checksum == NULL)
+ {
+ g_warning ("No appstream branch in remote %s\n", remote);
+ }
+ else
+ {
+ if (!flatpak_system_helper_call_deploy_appstream_sync (system_helper,
+ gs_file_get_path_cached (ostree_repo_get_path (child_repo)),
+ remote,
+ arch,
+ cancellable,
+ error))
+ return FALSE;
+ }
+
+ (void) glnx_shutil_rm_rf_at (AT_FDCWD,
+ gs_file_get_path_cached (ostree_repo_get_path (child_repo)),
+ NULL, NULL);
+
+ return TRUE;
+ }
+
+ if (!flatpak_dir_pull (self, remote, branch, NULL, NULL, OSTREE_REPO_PULL_FLAGS_NONE, progress,
+ cancellable, error))
+ return FALSE;
+
+ remote_and_branch = g_strdup_printf ("%s:%s", remote, branch);
+
+ if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, &new_checksum, error))
+ return FALSE;
+
+ if (new_checksum == NULL)
+ {
+ g_warning ("No appstream branch in remote %s\n", remote);
+ return TRUE;
+ }
+
+ return flatpak_dir_deploy_appstream (self,
+ remote,
+ arch,
+ out_changed,
+ cancellable,
+ error);
+}
+
/* This is a copy of ostree_repo_pull_one_dir that always disables
static deltas if subdir is used */
static gboolean
diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h
index 495b81f..f40811f 100644
--- a/common/flatpak-dir.h
+++ b/common/flatpak-dir.h
@@ -165,6 +165,12 @@ 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,
diff --git a/data/org.freedesktop.Flatpak.xml b/data/org.freedesktop.Flatpak.xml
index e91cda3..8ef52bc 100644
--- a/data/org.freedesktop.Flatpak.xml
+++ b/data/org.freedesktop.Flatpak.xml
@@ -39,6 +39,12 @@
<arg type='s' name='origin' direction='in'/>
<arg type='as' name='subpaths' direction='in'/>
</method>
+
+ <method name="DeployAppstream">
+ <arg type='ay' name='repo_path' direction='in'/>
+ <arg type='s' name='origin' direction='in'/>
+ <arg type='s' name='arch' direction='in'/>
+ </method>
</interface>
</node>
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index 918d6b2..20a9e0e 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -158,6 +158,71 @@ handle_deploy (FlatpakSystemHelper *object,
return TRUE;
}
+static gboolean
+handle_deploy_appstream (FlatpakSystemHelper *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_repo_path,
+ const gchar *arg_origin,
+ const gchar *arg_arch)
+{
+ g_autoptr(FlatpakDir) system = flatpak_dir_get_system ();
+ g_autoptr(GFile) path = g_file_new_for_path (arg_repo_path);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GMainContext) main_context = NULL;
+ g_autofree char *branch = NULL;
+
+ if (!g_file_query_exists (path, NULL))
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Path does not exist");
+ return TRUE;
+ }
+
+ if (!flatpak_dir_ensure_repo (system, NULL, &error))
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Can't open system repo %s", error->message);
+ return TRUE;
+ }
+
+ /* Work around ostree-pull spinning the default main context for the sync calls */
+ main_context = g_main_context_new ();
+ g_main_context_push_thread_default (main_context);
+
+ branch = g_strdup_printf ("appstream/%s", arg_arch);
+
+ g_print ("pulling branch %s\n", branch);
+
+ if (!flatpak_dir_pull_untrusted_local (system, arg_repo_path,
+ arg_origin,
+ branch,
+ NULL,
+ NULL,
+ NULL, &error))
+ {
+ g_main_context_pop_thread_default (main_context);
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Error pulling from repo: %s", error->message);
+ return TRUE;
+ }
+
+ g_main_context_pop_thread_default (main_context);
+
+ if (!flatpak_dir_deploy_appstream (system,
+ arg_origin,
+ arg_arch,
+ NULL,
+ NULL,
+ &error))
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Error deploying appstream: %s", error->message);
+ return TRUE;
+ }
+
+ flatpak_system_helper_complete_deploy_appstream (object, invocation);
+
+ return TRUE;
+}
static gboolean
flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
@@ -229,6 +294,32 @@ flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
authorized = polkit_authorization_result_get_is_authorized (result);
}
+ else if (g_strcmp0 (method_name, "DeployAppstream") == 0)
+ {
+ const char *arch, *origin;
+
+ g_variant_get_child (parameters, 1, "&s", &origin);
+ g_variant_get_child (parameters, 2, "&s", &arch);
+
+ action = "org.freedesktop.Flatpak.appstream-update";
+
+ details = polkit_details_new ();
+ polkit_details_insert (details, "origin", origin);
+ polkit_details_insert (details, "arch", arch);
+
+ result = polkit_authority_check_authorization_sync (authority, subject,
+ action, details,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL, &error);
+ if (result == NULL)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Authorization error: %s", error->message);
+ return FALSE;
+ }
+
+ authorized = polkit_authorization_result_get_is_authorized (result);
+ }
if (!authorized)
{
@@ -256,6 +347,7 @@ on_bus_acquired (GDBusConnection *connection,
G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
g_signal_connect (helper, "handle-deploy", G_CALLBACK (handle_deploy), NULL);
+ g_signal_connect (helper, "handle-deploy-appstream", G_CALLBACK (handle_deploy_appstream), NULL);
g_signal_connect (helper, "g-authorize-method",
G_CALLBACK (flatpak_authorize_method_handler),
diff --git a/system-helper/org.freedesktop.Flatpak.policy.in b/system-helper/org.freedesktop.Flatpak.policy.in
index a420339..a0a1bcc 100644
--- a/system-helper/org.freedesktop.Flatpak.policy.in
+++ b/system-helper/org.freedesktop.Flatpak.policy.in
@@ -83,4 +83,22 @@
</defaults>
</action>
+ <action id="org.freedesktop.Flatpak.appstream-update">
+ <!-- SECURITY:
+ - Normal users do not require admin authentication to update
+ appstream data as it will be signed, and the action is required
+ to update the system when unattended.
+ - Changing this to anything other than 'yes' will break unattended
+ updates.
+ -->
+ <_description>Update appstream</_description>
+ <_message>Authentication is required to update software</_message>
+ <icon_name>package-x-generic</icon_name>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>