flatpak_dir_setup_revokefs_fuse_mount (FlatpakDir    *self,
                                       FlatpakDecomposed *ref,
                                       const gchar   *installation,
                                       gchar        **out_src_dir,
                                       gchar        **out_mnt_dir,
                                       GCancellable  *cancellable)
{
  g_autoptr (GError) local_error = NULL;
  g_autofree gchar *src_dir_tmp = NULL;
  g_autofree gchar *mnt_dir_tmp = NULL;
  gint socket = -1;
  gboolean res = FALSE;
  const char *revokefs_fuse_bin = LIBEXECDIR "/revokefs-fuse";

  if (g_getenv ("FLATPAK_REVOKEFS_FUSE"))
    revokefs_fuse_bin = g_getenv ("FLATPAK_REVOKEFS_FUSE");

  if (!flatpak_dir_system_helper_call_get_revokefs_fd (self,
                                                       FLATPAK_HELPER_GET_REVOKEFS_FD_FLAGS_NONE,
                                                       installation ? installation : "",
                                                       &socket,
                                                       &src_dir_tmp,
                                                       cancellable,
                                                       &local_error))
    {
      if (g_error_matches (local_error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED))
        g_debug ("revokefs-fuse not supported on your installation: %s", local_error->message);
      else
        g_warning ("Failed to get revokefs-fuse socket from system-helper: %s", local_error->message);

      goto out;
    }
  else
    {
      g_autoptr(GSubprocess) revokefs_fuse = NULL;
      g_autoptr(GSubprocessLauncher) launcher = NULL;
      g_autofree gchar *client_uid = NULL;

      mnt_dir_tmp = flatpak_dir_revokefs_fuse_create_mountpoint (ref, &local_error);
      if (mnt_dir_tmp == NULL)
        {
          g_warning ("Failed to create a mountpoint for revokefs-fuse: %s", local_error->message);
          close (socket);
          goto out;
        }

      client_uid = g_strdup_printf ("uid=%d", getuid ());
      launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
      g_subprocess_launcher_take_fd (launcher, socket, 3);
      revokefs_fuse = g_subprocess_launcher_spawn (launcher,
                                                   &local_error,
                                                   revokefs_fuse_bin, "-o", client_uid, "--socket=3",
                                                   src_dir_tmp, mnt_dir_tmp, NULL);
      if (revokefs_fuse == NULL ||
          !g_subprocess_wait_check (revokefs_fuse, NULL, &local_error))
        {
          g_warning ("Error spawning revokefs-fuse: %s", local_error->message);
          close (socket);
          goto out;
        }
    }

  res = TRUE;

out:
  /* It is unconventional to steal these values on error. However, it depends on where
   * this function failed. If we are able to spawn the revokefs backend (src_dir_tmp
   * is non-NULL) but failed to create mountpoint or spawning revokefs-fuse here,
   * we  still need the src_dir_tmp value to cleanup the revokefs backend properly
   * through the system-helper's CancelPull(). Hence, always stealing values can tell
   * the caller under what circumstances this function failed and cleanup accordingly. */
  *out_mnt_dir = g_steal_pointer (&mnt_dir_tmp);
  *out_src_dir = g_steal_pointer (&src_dir_tmp);

  return res;
}