summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--Makefile.am2
-rw-r--r--app/flatpak-builtins-document-export.c2
-rw-r--r--app/flatpak-builtins-document-info.c2
-rw-r--r--app/flatpak-builtins-document-list.c2
-rw-r--r--app/flatpak-builtins-document-unexport.c2
-rw-r--r--common/Makefile.am.inc20
-rw-r--r--common/flatpak-context.c1
-rw-r--r--common/flatpak-db.c1224
-rw-r--r--common/flatpak-db.h103
-rw-r--r--common/flatpak-exports.c1
-rw-r--r--common/flatpak-run.c2
-rw-r--r--common/flatpak-utils.h2
-rw-r--r--common/gvdb/.gitignore2
-rw-r--r--common/gvdb/README7
-rw-r--r--common/gvdb/gvdb-builder.c537
-rw-r--r--common/gvdb/gvdb-builder.h60
-rw-r--r--common/gvdb/gvdb-format.h85
-rw-r--r--common/gvdb/gvdb-reader.c718
-rw-r--r--common/gvdb/gvdb-reader.h63
-rw-r--r--common/gvdb/gvdb.doap32
-rw-r--r--data/Makefile.am.inc3
-rw-r--r--data/org.freedesktop.impl.portal.PermissionStore.xml163
-rw-r--r--document-portal/Makefile.am.inc43
-rw-r--r--document-portal/org.freedesktop.portal.Documents.service.in4
-rw-r--r--document-portal/xdg-document-portal.service.in7
-rw-r--r--document-portal/xdp-enums.h25
-rw-r--r--document-portal/xdp-fuse.c2369
-rw-r--r--document-portal/xdp-fuse.h23
-rw-r--r--document-portal/xdp-main.c1558
-rw-r--r--document-portal/xdp-util.c129
-rw-r--r--document-portal/xdp-util.h33
-rw-r--r--permission-store/Makefile.am.inc37
-rw-r--r--permission-store/org.freedesktop.impl.portal.PermissionStore.service.in4
-rw-r--r--permission-store/permission-store.c146
-rw-r--r--permission-store/xdg-permission-store.c468
-rw-r--r--permission-store/xdg-permission-store.h28
-rw-r--r--permission-store/xdg-permission-store.service.in7
-rw-r--r--tests/Makefile.am.inc41
-rw-r--r--tests/dbs/no_tablesbin32 -> 0 bytes
-rw-r--r--tests/test-doc-portal.c505
-rw-r--r--tests/testdb.c359
42 files changed, 19 insertions, 8806 deletions
diff --git a/.gitignore b/.gitignore
index d14be5f2..dbe9d7ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,7 +36,6 @@ flatpak-session-helper
xdg-document-portal
xdg-permission-store
flatpak-builder
-testdb
*~
profile/flatpak.sh
flatpak-dbus.[ch]
@@ -68,9 +67,6 @@ Flatpak-1.0.*
/doc/flatpak-docs.xml
/doc/*.1
/doc/*.5
-/test-doc-portal
-/test-doc-portal.log
-/test-doc-portal.trs
/test-libglnx-errors
/test-libglnx-errors.log
/test-libglnx-errors.trs
@@ -89,8 +85,6 @@ Flatpak-1.0.*
/testlibrary
/testlibrary.log
/testlibrary.trs
-/testdb.log
-/testdb.trs
/tests/test-keyring/.gpg-v21-migrated
/tests/test-keyring/private-keys-v1.d/
/tests/test-keyring/trustdb.gpg
diff --git a/Makefile.am b/Makefile.am
index 96b83ab1..ce2508ff 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -94,8 +94,6 @@ include lib/Makefile.am.inc
include session-helper/Makefile.am.inc
include system-helper/Makefile.am.inc
include dbus-proxy/Makefile.am.inc
-include permission-store/Makefile.am.inc
-include document-portal/Makefile.am.inc
include tests/Makefile.am.inc
if !WITH_SYSTEM_BWRAP
diff --git a/app/flatpak-builtins-document-export.c b/app/flatpak-builtins-document-export.c
index 1a16c7b0..46b4c944 100644
--- a/app/flatpak-builtins-document-export.c
+++ b/app/flatpak-builtins-document-export.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
-#include "document-portal/xdp-dbus.h"
+#include "flatpak-document-dbus.h"
#include <gio/gunixfdlist.h>
diff --git a/app/flatpak-builtins-document-info.c b/app/flatpak-builtins-document-info.c
index bd7edc68..c9605456 100644
--- a/app/flatpak-builtins-document-info.c
+++ b/app/flatpak-builtins-document-info.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
-#include "document-portal/xdp-dbus.h"
+#include "flatpak-document-dbus.h"
#include <gio/gunixfdlist.h>
diff --git a/app/flatpak-builtins-document-list.c b/app/flatpak-builtins-document-list.c
index 4644086c..48cd1afb 100644
--- a/app/flatpak-builtins-document-list.c
+++ b/app/flatpak-builtins-document-list.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
-#include "document-portal/xdp-dbus.h"
+#include "flatpak-document-dbus.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
diff --git a/app/flatpak-builtins-document-unexport.c b/app/flatpak-builtins-document-unexport.c
index 8efeeb76..82e58f38 100644
--- a/app/flatpak-builtins-document-unexport.c
+++ b/app/flatpak-builtins-document-unexport.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
-#include "document-portal/xdp-dbus.h"
+#include "flatpak-document-dbus.h"
#include <gio/gunixfdlist.h>
diff --git a/common/Makefile.am.inc b/common/Makefile.am.inc
index ea5afdb7..74db3b47 100644
--- a/common/Makefile.am.inc
+++ b/common/Makefile.am.inc
@@ -1,6 +1,6 @@
noinst_LTLIBRARIES += libflatpak-common.la
-dbus_built_sources = common/flatpak-dbus.c common/flatpak-dbus.h
+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
common/flatpak-dbus.c: data/org.freedesktop.Flatpak.xml Makefile
@@ -9,7 +9,16 @@ common/flatpak-dbus.c: data/org.freedesktop.Flatpak.xml Makefile
--interface-prefix org.freedesktop.Flatpak. \
--c-namespace Flatpak \
--generate-c-code $(builddir)/common/flatpak-dbus \
- $(srcdir)/data/org.freedesktop.Flatpak.xml \
+ $(srcdir)/data/org.freedesktop.Flatpak.xml \
+ $(NULL)
+
+common/flatpak-document-dbus.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 \
+ $(srcdir)/data/org.freedesktop.portal.Documents.xml \
$(NULL)
common/flatpak-systemd-dbus.c: data/org.freedesktop.systemd1.xml Makefile
@@ -53,13 +62,6 @@ libflatpak_common_la_SOURCES = \
common/flatpak-table-printer.h \
common/flatpak-chain-input-stream.c \
common/flatpak-chain-input-stream.h \
- common/gvdb/gvdb-reader.h \
- common/gvdb/gvdb-format.h \
- common/gvdb/gvdb-reader.c \
- common/gvdb/gvdb-builder.h \
- common/gvdb/gvdb-builder.c \
- common/flatpak-db.c \
- common/flatpak-db.h \
common/flatpak-json.c \
common/flatpak-json.h \
common/flatpak-json-oci.c \
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
index aae2726f..209e84fc 100644
--- a/common/flatpak-context.c
+++ b/common/flatpak-context.c
@@ -42,7 +42,6 @@
#include "flatpak-utils.h"
#include "flatpak-dir.h"
#include "flatpak-systemd-dbus.h"
-#include "document-portal/xdp-dbus.h"
#include "lib/flatpak-error.h"
/* Same order as enum */
diff --git a/common/flatpak-db.c b/common/flatpak-db.c
deleted file mode 100644
index f20443ed..00000000
--- a/common/flatpak-db.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/* flatpak-db.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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/statfs.h>
-
-#include "flatpak-db.h"
-#include "gvdb/gvdb-reader.h"
-#include "gvdb/gvdb-builder.h"
-
-struct FlatpakDb
-{
- GObject parent;
-
- char *path;
- gboolean fail_if_not_found;
- GvdbTable *gvdb;
- GBytes *gvdb_contents;
-
- gboolean dirty;
-
- /* Map id => GVariant (data, sorted-dict[appid->perms]) */
- GvdbTable *main_table;
- GHashTable *main_updates;
-
- /* (reverse) Map app id => [ id ]*/
- GvdbTable *app_table;
- GHashTable *app_additions;
- GHashTable *app_removals;
-};
-
-typedef struct
-{
- GObjectClass parent_class;
-} FlatpakDbClass;
-
-static void initable_iface_init (GInitableIface *initable_iface);
-
-G_DEFINE_TYPE_WITH_CODE (FlatpakDb, flatpak_db, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));
-
-enum {
- PROP_0,
- PROP_PATH,
- PROP_FAIL_IF_NOT_FOUND,
- LAST_PROP
-};
-
-static int
-cmpstringp (const void *p1, const void *p2)
-{
- return strcmp (*(char * const *) p1, *(char * const *) p2);
-}
-
-static void
-sort_strv (const char **strv)
-{
- qsort (strv, g_strv_length ((char **) strv), sizeof (const char *), cmpstringp);
-}
-
-static int
-str_ptr_array_find (GPtrArray *array,
- const char *str)
-{
- int i;
-
- for (i = 0; i < array->len; i++)
- if (strcmp (g_ptr_array_index (array, i), str) == 0)
- return i;
-
- return -1;
-}
-
-static gboolean
-str_ptr_array_contains (GPtrArray *array,
- const char *str)
-{
- return str_ptr_array_find (array, str) >= 0;
-}
-
-const char *
-flatpak_db_get_path (FlatpakDb *self)
-{
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- return self->path;
-}
-
-void
-flatpak_db_set_path (FlatpakDb *self,
- const char *path)
-{
- g_return_if_fail (FLATPAK_IS_DB (self));
-
- g_clear_pointer (&self->path, g_free);
- self->path = g_strdup (path);
-}
-
-FlatpakDb *
-flatpak_db_new (const char *path,
- gboolean fail_if_not_found,
- GError **error)
-{
- return g_initable_new (FLATPAK_TYPE_DB,
- NULL,
- error,
- "path", path,
- "fail-if-not-found", fail_if_not_found,
- NULL);
-}
-
-static void
-flatpak_db_finalize (GObject *object)
-{
- FlatpakDb *self = (FlatpakDb *) object;
-
- g_clear_pointer (&self->path, g_free);
- g_clear_pointer (&self->gvdb_contents, g_bytes_unref);
- g_clear_pointer (&self->gvdb, gvdb_table_free);
- g_clear_pointer (&self->main_table, gvdb_table_free);
- g_clear_pointer (&self->app_table, gvdb_table_free);
- g_clear_pointer (&self->main_updates, g_hash_table_unref);
- g_clear_pointer (&self->app_additions, g_hash_table_unref);
- g_clear_pointer (&self->app_removals, g_hash_table_unref);
-
- G_OBJECT_CLASS (flatpak_db_parent_class)->finalize (object);
-}
-
-static void
-flatpak_db_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- FlatpakDb *self = FLATPAK_DB (object);
-
- switch (prop_id)
- {
- case PROP_PATH:
- g_value_set_string (value, self->path);
- break;
-
- case PROP_FAIL_IF_NOT_FOUND:
- g_value_set_boolean (value, self->fail_if_not_found);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-flatpak_db_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- FlatpakDb *self = FLATPAK_DB (object);
-
- switch (prop_id)
- {
- case PROP_PATH:
- g_clear_pointer (&self->path, g_free);
- self->path = g_value_dup_string (value);
- break;
-
- case PROP_FAIL_IF_NOT_FOUND:
- self->fail_if_not_found = g_value_get_boolean (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-flatpak_db_class_init (FlatpakDbClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = flatpak_db_finalize;
- object_class->get_property = flatpak_db_get_property;
- object_class->set_property = flatpak_db_set_property;
-
- g_object_class_install_property (object_class,
- PROP_PATH,
- g_param_spec_string ("path",
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property (object_class,
- PROP_FAIL_IF_NOT_FOUND,
- g_param_spec_boolean ("fail-if-not-found",
- "",
- "",
- TRUE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-flatpak_db_init (FlatpakDb *self)
-{
- self->fail_if_not_found = TRUE;
-
- self->main_updates =
- g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_variant_unref);
- self->app_additions =
- g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_ptr_array_unref);
- self->app_removals =
- g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_ptr_array_unref);
-}
-
-static gboolean
-is_on_nfs (const char *path)
-{
- struct statfs statfs_buffer;
- int statfs_result;
- g_autofree char *dirname = NULL;
-
- dirname = g_path_get_dirname (path);
-
- statfs_result = statfs (dirname, &statfs_buffer);
- if (statfs_result != 0)
- return FALSE;
-
- return statfs_buffer.f_type == 0x6969;
-}
-
-static gboolean
-initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
-{
- FlatpakDb *self = (FlatpakDb *) initable;
- GError *my_error = NULL;
-
- if (self->path == NULL)
- return TRUE;
-
- if (is_on_nfs (self->path))
- {
- g_autoptr(GFile) file = g_file_new_for_path (self->path);
- char *contents;
- gsize length;
-
- /* We avoid using mmap on NFS, because its prone to give us SIGBUS at semi-random
- times (nfs down, file removed, etc). Instead we just load the file */
- if (g_file_load_contents (file, cancellable, &contents, &length, NULL, &my_error))
- self->gvdb_contents = g_bytes_new_take (contents, length);
- }
- else
- {
- GMappedFile *mapped = g_mapped_file_new (self->path, FALSE, &my_error);
- if (mapped)
- {
- self->gvdb_contents = g_mapped_file_get_bytes (mapped);
- g_mapped_file_unref (mapped);
- }
- }
-
- if (self->gvdb_contents == NULL)
- {
- if (!self->fail_if_not_found &&
- g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- {
- g_error_free (my_error);
- }
- else
- {
- g_propagate_error (error, my_error);
- return FALSE;
- }
- }
- else
- {
- self->gvdb = gvdb_table_new_from_bytes (self->gvdb_contents, TRUE, error);
- if (self->gvdb == NULL)
- return FALSE;
-
- self->main_table = gvdb_table_get_table (self->gvdb, "main");
- if (self->main_table == NULL)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No main table in db");
- return FALSE;
- }
-
- self->app_table = gvdb_table_get_table (self->gvdb, "apps");
- if (self->app_table == NULL)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No app table in db");
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static void
-initable_iface_init (GInitableIface *initable_iface)
-{
- initable_iface->init = initable_init;
-}
-
-/* Transfer: full */
-char **
-flatpak_db_list_ids (FlatpakDb *self)
-{
- GPtrArray *res;
- GHashTableIter iter;
- gpointer key, value;
- int i;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- res = g_ptr_array_new ();
-
- g_hash_table_iter_init (&iter, self->main_updates);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (value != NULL)
- g_ptr_array_add (res, g_strdup (key));
- }
-
- if (self->main_table)
- {
- // TODO: can we use gvdb_table_list here???
- g_autofree char **main_ids = gvdb_table_get_names (self->main_table, NULL);
-
- for (i = 0; main_ids[i] != NULL; i++)
- {
- char *id = main_ids[i];
-
- if (g_hash_table_lookup_extended (self->main_updates, id, NULL, NULL))
- g_free (id);
- else
- g_ptr_array_add (res, id);
- }
- }
-
- g_ptr_array_add (res, NULL);
- return (char **) g_ptr_array_free (res, FALSE);
-}
-
-static gboolean
-app_update_empty (GHashTable *ht, const char *app)
-{
- GPtrArray *array;
-
- array = g_hash_table_lookup (ht, app);
- if (array == NULL)
- return TRUE;
-
- return array->len == 0;
-}
-
-/* Transfer: full */
-char **
-flatpak_db_list_apps (FlatpakDb *self)
-{
- gpointer key, _value;
- GHashTableIter iter;
- GPtrArray *res;
- int i;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- res = g_ptr_array_new ();
-
- g_hash_table_iter_init (&iter, self->app_additions);
- while (g_hash_table_iter_next (&iter, &key, &_value))
- {
- GPtrArray *value = _value;
- if (value->len > 0)
- g_ptr_array_add (res, g_strdup (key));
- }
-
- if (self->app_table)
- {
- // TODO: can we use gvdb_table_list here???
- g_autofree char **apps = gvdb_table_get_names (self->app_table, NULL);
-
- for (i = 0; apps[i] != NULL; i++)
- {
- char *app = apps[i];
- gboolean empty = TRUE;
- GPtrArray *removals;
- int j;
-
- /* Don't use if we already added above */
- if (app_update_empty (self->app_additions, app))
- {
- g_autoptr(GVariant) ids_v = NULL;
-
- removals = g_hash_table_lookup (self->app_removals, app);
-
- /* Add unless all items are removed */
- ids_v = gvdb_table_get_value (self->app_table, app);
-
- if (ids_v)
- {
- g_autofree const char **ids = g_variant_get_strv (ids_v, NULL);
-
- for (j = 0; ids[j] != NULL; j++)
- {
- if (removals == NULL ||
- !str_ptr_array_contains (removals, ids[j]))
- {
- empty = FALSE;
- break;
- }
- }
- }
- }
-
- if (empty)
- g_free (app);
- else
- g_ptr_array_add (res, app);
- }
- }
-
- g_ptr_array_add (res, NULL);
- return (char **) g_ptr_array_free (res, FALSE);
-}
-
-/* Transfer: full */
-char **
-flatpak_db_list_ids_by_app (FlatpakDb *self,
- const char *app)
-{
- GPtrArray *res;
- GPtrArray *additions;
- GPtrArray *removals;
- int i;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- res = g_ptr_array_new ();
-
- additions = g_hash_table_lookup (self->app_additions, app);
- removals = g_hash_table_lookup (self->app_removals, app);
-
- if (additions)
- {
- for (i = 0; i < additions->len; i++)
- g_ptr_array_add (res,
- g_strdup (g_ptr_array_index (additions, i)));
- }
-
- if (self->app_table)
- {
- g_autoptr(GVariant) ids_v = gvdb_table_get_value (self->app_table, app);
- if (ids_v)
- {
- g_autofree const char **ids = g_variant_get_strv (ids_v, NULL);
-
- for (i = 0; ids[i] != NULL; i++)
- {
- if (removals == NULL ||
- !str_ptr_array_contains (removals, ids[i]))
- g_ptr_array_add (res, g_strdup (ids[i]));
- }
- }
- }
-
- g_ptr_array_add (res, NULL);
- return (char **) g_ptr_array_free (res, FALSE);
-}
-
-/* Transfer: full */
-FlatpakDbEntry *
-flatpak_db_lookup (FlatpakDb *self,
- const char *id)
-{
- GVariant *res = NULL;
- gpointer value;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
- g_return_val_if_fail (id != NULL, NULL);
-
- if (g_hash_table_lookup_extended (self->main_updates, id, NULL, &value))
- {
- if (value != NULL)
- res = g_variant_ref ((GVariant *) value);
- }
- else if (self->main_table)
- {
- res = gvdb_table_get_value (self->main_table, id);
- }
-
- return (FlatpakDbEntry *) res;
-}
-
-/* Transfer: full */
-char **
-flatpak_db_list_ids_by_value (FlatpakDb *self,
- GVariant *data)
-{
- g_autofree char **ids = flatpak_db_list_ids (self);
- int i;
- GPtrArray *res;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
- g_return_val_if_fail (data != NULL, NULL);
-
- res = g_ptr_array_new ();
-
- for (i = 0; ids[i] != NULL; i++)
- {
- char *id = ids[i];
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autoptr(GVariant) entry_data = NULL;
-
- entry = flatpak_db_lookup (self, id);
- if (entry)
- {
- entry_data = flatpak_db_entry_get_data (entry);
- if (g_variant_equal (data, entry_data))
- {
- g_ptr_array_add (res, id);
- id = NULL; /* Don't free, as we return this */
- }
- }
- g_free (id);
- }
-
- g_ptr_array_add (res, NULL);
- return (char **) g_ptr_array_free (res, FALSE);
-}
-
-static void
-add_app_id (FlatpakDb *self,
- const char *app,
- const char *id)
-{
- GPtrArray *additions;
- GPtrArray *removals;
- int i;
-
- additions = g_hash_table_lookup (self->app_additions, app);
- removals = g_hash_table_lookup (self->app_removals, app);
-
- if (removals)
- {
- i = str_ptr_array_find (removals, id);
- if (i >= 0)
- g_ptr_array_remove_index_fast (removals, i);
- }
-
- if (additions)
- {
- if (!str_ptr_array_contains (additions, id))
- g_ptr_array_add (additions, g_strdup (id));
- }
- else
- {
- additions = g_ptr_array_new_with_free_func (g_free);
- g_ptr_array_add (additions, g_strdup (id));
- g_hash_table_insert (self->app_additions,
- g_strdup (app), additions);
- }
-}
-
-static void
-remove_app_id (FlatpakDb *self,
- const char *app,
- const char *id)
-{
- GPtrArray *additions;
- GPtrArray *removals;
- int i;
-
- additions = g_hash_table_lookup (self->app_additions, app);
- removals = g_hash_table_lookup (self->app_removals, app);
-
- if (additions)
- {
- i = str_ptr_array_find (additions, id);
- if (i >= 0)
- g_ptr_array_remove_index_fast (additions, i);
- }
-
- if (removals)
- {
- if (!str_ptr_array_contains (removals, id))
- g_ptr_array_add (removals, g_strdup (id));
- }
- else
- {
- removals = g_ptr_array_new_with_free_func (g_free);
- g_ptr_array_add (removals, g_strdup (id));
- g_hash_table_insert (self->app_removals,
- g_strdup (app), removals);
- }
-}
-
-gboolean
-flatpak_db_is_dirty (FlatpakDb *self)
-{
- g_return_val_if_fail (FLATPAK_IS_DB (self), FALSE);
-
- return self->dirty;
-}
-
-/* add, replace, or NULL entry to remove */
-void
-flatpak_db_set_entry (FlatpakDb *self,
- const char *id,
- FlatpakDbEntry *entry)
-{
- g_autoptr(FlatpakDbEntry) old_entry = NULL;
- g_autofree const char **old = NULL;
- g_autofree const char **new = NULL;
- static const char *empty[] = { NULL };
- const char **a, **b;
- int ia, ib;
-
- g_return_if_fail (FLATPAK_IS_DB (self));
- g_return_if_fail (id != NULL);
-
- self->dirty = TRUE;
-
- old_entry = flatpak_db_lookup (self, id);
-
- g_hash_table_insert (self->main_updates,
- g_strdup (id),
- flatpak_db_entry_ref (entry));
-
- a = empty;
- b = empty;
-
- if (old_entry)
- {
- old = flatpak_db_entry_list_apps (old_entry);
- sort_strv (old);
- a = old;
- }
-
- if (entry)
- {
- new = flatpak_db_entry_list_apps (entry);
- sort_strv (new);
- b = new;
- }
-
- ia = 0;
- ib = 0;
- while (a[ia] != NULL || b[ib] != NULL)
- {
- if (a[ia] == NULL)
- {
- /* Not in old, but in new => added */
- add_app_id (self, b[ib], id);
- ib++;
- }
- else if (b[ib] == NULL)
- {
- /* Not in new, but in old => removed */
- remove_app_id (self, a[ia], id);
- ia++;
- }
- else
- {
- int cmp = strcmp (a[ia], b[ib]);
-
- if (cmp == 0)
- {
- /* In both, no change */
- ia++;
- ib++;
- }
- else if (cmp < 0)
- {
- /* Not in new, but in old => removed */
- remove_app_id (self, a[ia], id);
- ia++;
- }
- else /* cmp > 0 */
- {
- /* Not in old, but in new => added */
- add_app_id (self, b[ib], id);
- ib++;
- }
- }
- }
-}
-
-void
-flatpak_db_update (FlatpakDb *self)
-{
- GHashTable *root, *main_h, *apps_h;
- GBytes *new_contents;
- GvdbTable *new_gvdb;
- int i;
-
- g_auto(GStrv) ids = NULL;
- g_auto(GStrv) apps = NULL;
-
- g_return_if_fail (FLATPAK_IS_DB (self));
-
- root = gvdb_hash_table_new (NULL, NULL);
- main_h = gvdb_hash_table_new (root, "main");
- apps_h = gvdb_hash_table_new (root, "apps");
- g_hash_table_unref (main_h);
- g_hash_table_unref (apps_h);
-
- ids = flatpak_db_list_ids (self);
- for (i = 0; ids[i] != 0; i++)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (self, ids[i]);
- if (entry != NULL)
- {
- GvdbItem *item;
-
- item = gvdb_hash_table_insert (main_h, ids[i]);
- gvdb_item_set_value (item, (GVariant *) entry);
- }
- }
-
- apps = flatpak_db_list_apps (self);
- for (i = 0; apps[i] != 0; i++)
- {
- g_auto(GStrv) app_ids = flatpak_db_list_ids_by_app (self, apps[i]);
- GVariantBuilder builder;
- GvdbItem *item;
- int j;
-
- /* May as well ensure that on-disk arrays are sorted, even if we don't use it yet */
- sort_strv ((const char **) app_ids);
-
- /* We should never list an app that has empty id lists */
- g_assert (app_ids[0] != NULL);
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
- for (j = 0; app_ids[j] != NULL; j++)
- g_variant_builder_add (&builder, "s", app_ids[j]);
-
- item = gvdb_hash_table_insert (apps_h, apps[i]);
- gvdb_item_set_value (item, g_variant_builder_end (&builder));
- }
-
- new_contents = gvdb_table_get_content (root, FALSE);
- new_gvdb = gvdb_table_new_from_bytes (new_contents, TRUE, NULL);
-
- /* This was just created, any failure to parse it is purely an internal error */
- g_assert (new_gvdb != NULL);
-
- g_clear_pointer (&self->gvdb_contents, g_bytes_unref);
- g_clear_pointer (&self->gvdb, gvdb_table_free);
- self->gvdb_contents = new_contents;
- self->gvdb = new_gvdb;
- self->dirty = FALSE;
-}
-
-GBytes *
-flatpak_db_get_content (FlatpakDb *self)
-{
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- return self->gvdb_contents;
-}
-
-/* Note: You must first call update to serialize, this only saves serialied data */
-gboolean
-flatpak_db_save_content (FlatpakDb *self,
- GError **error)
-{
- GBytes *content = NULL;
-
- if (self->gvdb_contents == NULL)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No content to save");
- return FALSE;
- }
-
- if (self->path == NULL)
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No path set");
- return FALSE;
- }
-
- content = self->gvdb_contents;
- return g_file_set_contents (self->path, g_bytes_get_data (content, NULL), g_bytes_get_size (content), error);
-}
-
-static void
-save_content_callback (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- g_autoptr(GTask) task = user_data;
- GFile *file = G_FILE (source_object);
- gboolean ok;
- g_autoptr(GError) error = NULL;
-
- ok = g_file_replace_contents_finish (file,
- res,
- NULL, &error);
- if (ok)
- g_task_return_boolean (task, TRUE);
- else
- g_task_return_error (task, error);
-}
-
-void
-flatpak_db_save_content_async (FlatpakDb *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GBytes *content = NULL;
-
- g_autoptr(GTask) task = NULL;
- g_autoptr(GFile) file = NULL;
-
- task = g_task_new (self, cancellable, callback, user_data);
-
- if (self->gvdb_contents == NULL)
- {
- g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No content to save");
- return;
- }
-
- if (self->path == NULL)
- {
- g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "No path set");
- return;
- }
-
- content = g_bytes_ref (self->gvdb_contents);
- g_task_set_task_data (task, content, (GDestroyNotify) g_bytes_unref);
-
- file = g_file_new_for_path (self->path);
- g_file_replace_contents_bytes_async (file, content,
- NULL, FALSE, 0,
- cancellable,
- save_content_callback,
- g_object_ref (task));
-}
-
-gboolean
-flatpak_db_save_content_finish (FlatpakDb *self,
- GAsyncResult *res,
- GError **error)
-{
- return g_task_propagate_boolean (G_TASK (res), error);
-}
-
-
-GString *
-flatpak_db_print_string (FlatpakDb *self,
- GString *string)
-{
- g_auto(GStrv) ids = NULL;
- g_auto(GStrv) apps = NULL;
- int i;
-
- g_return_val_if_fail (FLATPAK_IS_DB (self), NULL);
-
- if G_UNLIKELY (string == NULL)
- string = g_string_new (NULL);
-
- g_string_append_printf (string, "main {\n");
-
- ids = flatpak_db_list_ids (self);
- sort_strv ((const char **) ids);
- for (i = 0; ids[i] != 0; i++)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (self, ids[i]);
- g_string_append_printf (string, " %s: ", ids[i]);
- if (entry != NULL)
- flatpak_db_entry_print_string (entry, string);
- g_string_append_printf (string, "\n");
- }
-
- g_string_append_printf (string, "}\napps {\n");
-
- apps = flatpak_db_list_apps (self);
- sort_strv ((const char **) apps);
- for (i = 0; apps[i] != 0; i++)
- {
- int j;
- g_auto(GStrv) app_ids = NULL;
-
- app_ids = flatpak_db_list_ids_by_app (self, apps[i]);
- sort_strv ((const char **) app_ids);
-
- g_string_append_printf (string, " %s: ", apps[i]);
- for (j = 0; app_ids[j] != NULL; j++)
- g_string_append_printf (string, "%s%s", j == 0 ? "" : ", ", app_ids[j]);
- g_string_append_printf (string, "\n");
- }
-
- g_string_append_printf (string, "}\n");
-
- return string;
-}
-
-char *
-flatpak_db_print (FlatpakDb *self)
-{
- return g_string_free (flatpak_db_print_string (self, NULL), FALSE);
-}
-
-FlatpakDbEntry *
-flatpak_db_entry_ref (FlatpakDbEntry *entry)
-{
- if (entry != NULL)
- g_variant_ref ((GVariant *) entry);
- return entry;
-}
-
-void
-flatpak_db_entry_unref (FlatpakDbEntry *entry)
-{
- g_variant_unref ((GVariant *) entry);
-}
-
-/* Transfer: full */
-GVariant *
-flatpak_db_entry_get_data (FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) variant = g_variant_get_child_value ((GVariant *) entry, 0);
-
- return g_variant_get_child_value (variant, 0);
-}
-
-/* Transfer: container */
-const char **
-flatpak_db_entry_list_apps (FlatpakDbEntry *entry)
-{
- GVariant *v = (GVariant *) entry;
-
- g_autoptr(GVariant) app_array = NULL;
- GVariantIter iter;
- GVariant *child;
- GPtrArray *res;
-
- res = g_ptr_array_new ();
-
- app_array = g_variant_get_child_value (v, 1);
-
- g_variant_iter_init (&iter, app_array);
- while ((child = g_variant_iter_next_value (&iter)))
- {
- const char *child_app_id;
- g_autoptr(GVariant) permissions = g_variant_get_child_value (child, 1);
-
- if (g_variant_n_children (permissions) > 0)
- {
- g_variant_get_child (child, 0, "&s", &child_app_id);
- g_ptr_array_add (res, (char *) child_app_id);
- }
-
- g_variant_unref (child);
- }
-
- g_ptr_array_add (res, NULL);
- return (const char **) g_ptr_array_free (res, FALSE);
-}
-
-static GVariant *
-flatpak_db_entry_get_permissions_variant (FlatpakDbEntry *entry,
- const char *app_id)
-{
- GVariant *v = (GVariant *) entry;
-
- g_autoptr(GVariant) app_array = NULL;
- GVariant *child;
- GVariant *res = NULL;
- gsize n_children, start, end, m;
- const char *child_app_id;
- int cmp;
-
- app_array = g_variant_get_child_value (v, 1);
-
- n_children = g_variant_n_children (app_array);
-
- start = 0;
- end = n_children;
- while (start < end)
- {
- m = (start + end) / 2;
-
- child = g_variant_get_child_value (app_array, m);
- g_variant_get_child (child, 0, "&s", &child_app_id);
-
- cmp = strcmp (app_id, child_app_id);
- if (cmp == 0)
- {
- res = g_variant_get_child_value (child, 1);
- break;
- }
- else if (cmp < 0)
- {
- end = m;
- }
- else /* cmp > 0 */
- {
- start = m + 1;
- }
- }
-
- return res;
-}
-
-
-/* Transfer: container */
-const char **
-flatpak_db_entry_list_permissions (FlatpakDbEntry *entry,
- const char *app)
-{
- g_autoptr(GVariant) permissions = NULL;
-
- permissions = flatpak_db_entry_get_permissions_variant (entry, app);
- if (permissions)
- return g_variant_get_strv (permissions, NULL);
- else
- return g_new0 (const char *, 1);
-}
-
-gboolean
-flatpak_db_entry_has_permission (FlatpakDbEntry *entry,
- const char *app,
- const char *permission)
-{
- g_autofree const char **app_permissions = NULL;
-
- app_permissions = flatpak_db_entry_list_permissions (entry, app);
-
- return g_strv_contains (app_permissions, permission);
-}
-
-gboolean
-flatpak_db_entry_has_permissions (FlatpakDbEntry *entry,
- const char *app,
- const char **permissions)
-{
- g_autofree const char **app_permissions = NULL;
- int i;
-
- app_permissions = flatpak_db_entry_list_permissions (entry, app);
-
- for (i = 0; permissions[i] != NULL; i++)
- {
- if (!g_strv_contains (app_permissions, permissions[i]))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static GVariant *
-make_entry (GVariant *data,
- GVariant *app_permissions)
-{
- return g_variant_new ("(v@a{sas})", data, app_permissions);
-}
-
-static GVariant *
-make_empty_app_permissions (void)
-{
- return g_variant_new_array (G_VARIANT_TYPE ("{sas}"), NULL, 0);
-}
-
-static GVariant *
-make_permissions (const char *app, const char **permissions)
-{
- static const char **empty = { NULL };
-
- if (permissions == NULL)
- permissions = empty;
-
- return g_variant_new ("{s@as}",
- app,
- g_variant_new_strv (permissions, -1));
-}
-
-static GVariant *
-add_permissions (GVariant *app_permissions,
- GVariant *permissions)
-{
- GVariantBuilder builder;
- GVariantIter iter;
- GVariant *child;
- gboolean added = FALSE;
- int cmp;
- const char *new_app_id;
- const char *child_app_id;
-
- g_autoptr(GVariant) new_perms_array = NULL;
-
- g_variant_get (permissions, "{&s@as}", &new_app_id, &new_perms_array);
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
-
- /* Insert or replace permissions in sorted order */
-
- g_variant_iter_init (&iter, app_permissions);
- while ((child = g_variant_iter_next_value (&iter)))
- {
- g_autoptr(GVariant) old_perms_array = NULL;
-
- g_variant_get (child, "{&s@as}", &child_app_id, &old_perms_array);
-
- cmp = strcmp (new_app_id, child_app_id);
- if (cmp == 0)
- {
- added = TRUE;
- /* Replace old permissions */
- g_variant_builder_add_value (&builder, permissions);
- }
- else if (cmp < 0)
- {
- if (!added)
- {
- added = TRUE;
- g_variant_builder_add_value (&builder, permissions);
- }
- g_variant_builder_add_value (&builder, child);
- }
- else /* cmp > 0 */
- {
- g_variant_builder_add_value (&builder, child);
- }
-
- g_variant_unref (child);
- }
-
- if (!added)
- g_variant_builder_add_value (&builder, permissions);
-
- return g_variant_builder_end (&builder);
-}
-
-FlatpakDbEntry *
-flatpak_db_entry_new (GVariant *data)
-{
- GVariant *res;
-
- if (data == NULL)
- data = g_variant_new_byte (0);
-
- res = make_entry (data,
- make_empty_app_permissions ());
-
- return (FlatpakDbEntry *) g_variant_ref_sink (res);
-}
-
-FlatpakDbEntry *
-flatpak_db_entry_modify_data (FlatpakDbEntry *entry,
- GVariant *data)
-{
- GVariant *v = (GVariant *) entry;
- GVariant *res;
-
- if (data == NULL)
- data = g_variant_new_byte (0);
-
- res = make_entry (data,
- g_variant_get_child_value (v, 1));
- return (FlatpakDbEntry *) g_variant_ref_sink (res);
-}
-
-/* NULL (or empty) permissions to remove permissions */
-FlatpakDbEntry *
-flatpak_db_entry_set_app_permissions (FlatpakDbEntry *entry,
- const char *app,
- const char **permissions)
-{
- GVariant *v = (GVariant *) entry;
- GVariant *res;
-
- g_autoptr(GVariant) old_data_v = g_variant_get_child_value (v, 0);
- g_autoptr(GVariant) old_data = g_variant_get_child_value (old_data_v, 0);
- g_autoptr(GVariant) old_permissions = g_variant_get_child_value (v, 1);
-
- res = make_entry (old_data,
- add_permissions (old_permissions,
- make_permissions (app,
- permissions)));
- return (FlatpakDbEntry *) g_variant_ref_sink (res);
-}
-
-GString *
-flatpak_db_entry_print_string (FlatpakDbEntry *entry,
- GString *string)
-{
- return g_variant_print_string ((GVariant *) entry, string, FALSE);
-}
diff --git a/common/flatpak-db.h b/common/flatpak-db.h
deleted file mode 100644
index f7757854..00000000
--- a/common/flatpak-db.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* flatpak-db.h
- *
- * Copyright © 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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef FLATPAK_DB_H
-#define FLATPAK_DB_H
-
-#include <string.h>
-
-#include "libglnx/libglnx.h"
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-typedef struct FlatpakDb FlatpakDb;
-typedef struct _FlatpakDbEntry FlatpakDbEntry;
-
-#define FLATPAK_TYPE_DB (flatpak_db_get_type ())
-#define FLATPAK_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DB, FlatpakDb))
-#define FLATPAK_IS_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DB))
-
-GType flatpak_db_get_type (void);
-
-FlatpakDb * flatpak_db_new (const char *path,
- gboolean fail_if_not_found,
- GError **error);
-char ** flatpak_db_list_ids (FlatpakDb *self);
-char ** flatpak_db_list_apps (FlatpakDb *self);
-char ** flatpak_db_list_ids_by_app (FlatpakDb *self,
- const char *app);
-char ** flatpak_db_list_ids_by_value (FlatpakDb *self,
- GVariant *data);
-FlatpakDbEntry *flatpak_db_lookup (FlatpakDb *self,
- const char *id);
-GString * flatpak_db_print_string (FlatpakDb *self,
- GString *string);
-char * flatpak_db_print (FlatpakDb *self);
-
-gboolean flatpak_db_is_dirty (FlatpakDb *self);
-void flatpak_db_set_entry (FlatpakDb *self,
- const char *id,
- FlatpakDbEntry *entry);
-void flatpak_db_update (FlatpakDb *self);
-GBytes * flatpak_db_get_content (FlatpakDb *self);
-const char * flatpak_db_get_path (FlatpakDb *self);
-gboolean flatpak_db_save_content (FlatpakDb *self,
- GError **error);
-void flatpak_db_save_content_async (FlatpakDb *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean flatpak_db_save_content_finish (FlatpakDb *self,
- GAsyncResult *res,
- GError **error);
-void flatpak_db_set_path (FlatpakDb *self,
- const char *path);
-
-
-FlatpakDbEntry *flatpak_db_entry_ref (FlatpakDbEntry *entry);
-void flatpak_db_entry_unref (FlatpakDbEntry *entry);
-GVariant * flatpak_db_entry_get_data (FlatpakDbEntry *entry);
-const char ** flatpak_db_entry_list_apps (FlatpakDbEntry *entry);
-const char ** flatpak_db_entry_list_permissions (FlatpakDbEntry *entry,
- const char *app);
-gboolean flatpak_db_entry_has_permission (FlatpakDbEntry *entry,
- const char *app,
- const char *permission);
-gboolean flatpak_db_entry_has_permissions (FlatpakDbEntry *entry,
- const char *app,
- const char **permissions);
-GString * flatpak_db_entry_print_string (FlatpakDbEntry *entry,
- GString *string);
-
-FlatpakDbEntry *flatpak_db_entry_new (GVariant *data);
-FlatpakDbEntry *flatpak_db_entry_modify_data (FlatpakDbEntry *entry,
- GVariant *data);
-FlatpakDbEntry *flatpak_db_entry_set_app_permissions (FlatpakDbEntry *entry,
- const char *app,
- const char **permissions);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDb, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDbEntry, flatpak_db_entry_unref)
-
-G_END_DECLS
-
-#endif /* FLATPAK_DB_H */
diff --git a/common/flatpak-exports.c b/common/flatpak-exports.c
index 586a3527..64eb8e1b 100644
--- a/common/flatpak-exports.c
+++ b/common/flatpak-exports.c
@@ -43,7 +43,6 @@
#include "flatpak-utils.h"
#include "flatpak-dir.h"
#include "flatpak-systemd-dbus.h"
-#include "document-portal/xdp-dbus.h"
#include "lib/flatpak-error.h"
/* We don't want to export paths pointing into these, because they are readonly
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 8638f713..2637b0c5 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -50,7 +50,7 @@
#include "flatpak-utils.h"
#include "flatpak-dir.h"
#include "flatpak-systemd-dbus.h"
-#include "document-portal/xdp-dbus.h"
+#include "flatpak-document-dbus.h"
#include "lib/flatpak-error.h"
#define DEFAULT_SHELL "/bin/sh"
diff --git a/common/flatpak-utils.h b/common/flatpak-utils.h
index 52a72a3c..9e5bf7e4 100644
--- a/common/flatpak-utils.h
+++ b/common/flatpak-utils.h
@@ -29,9 +29,9 @@
#include <gio/gunixfdlist.h>
#include <libsoup/soup.h>
#include "flatpak-dbus.h"
+#include "flatpak-document-dbus.h"
#include <ostree.h>
#include <json-glib/json-glib.h>
-#include "document-portal/xdp-dbus.h"
typedef enum {
FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV = 1 << 0,
diff --git a/common/gvdb/.gitignore b/common/gvdb/.gitignore
deleted file mode 100644
index 8b5dee6a..00000000
--- a/common/gvdb/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-libgvdb.a
-libgvdb-shared.a
diff --git a/common/gvdb/README b/common/gvdb/README
deleted file mode 100644
index 94e6c5d1..00000000
--- a/common/gvdb/README
+++ /dev/null
@@ -1,7 +0,0 @@
-DO NOT MODIFY ANY FILE IN THIS DIRECTORY
-
-(except maybe the Makefile.am)
-
-This directory is the result of a git subtree merge with the 'gvdb'
-module on git.gnome.org. Please apply fixes to the 'gvdb' module and
-perform a git merge.
diff --git a/common/gvdb/gvdb-builder.c b/common/gvdb/gvdb-builder.c
deleted file mode 100644
index ded77086..00000000
--- a/common/gvdb/gvdb-builder.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright © 2010 Codethink Limited
- *
- * 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 of the licence, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#include "gvdb-builder.h"
-#include "gvdb-format.h"
-
-#include <glib.h>
-#include <fcntl.h>
-#if !defined(G_OS_WIN32) || !defined(_MSC_VER)
-#include <unistd.h>
-#endif
-#include <string.h>
-
-
-struct _GvdbItem
-{
- gchar *key;
- guint32 hash_value;
- guint32_le assigned_index;
- GvdbItem *parent;
- GvdbItem *sibling;
- GvdbItem *next;
-
- /* one of:
- * this:
- */
- GVariant *value;
-
- /* this: */
- GHashTable *table;
-
- /* or this: */
- GvdbItem *child;
-};
-
-static void
-gvdb_item_free (gpointer data)
-{
- GvdbItem *item = data;
-
- g_free (item->key);
-
- if (item->value)
- g_variant_unref (item->value);
-
- if (item->table)
- g_hash_table_unref (item->table);
-
- g_slice_free (GvdbItem, item);
-}
-
-GHashTable *
-gvdb_hash_table_new (GHashTable *parent,
- const gchar *name_in_parent)
-{
- GHashTable *table;
-
- table = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, gvdb_item_free);
-
- if (parent)
- {
- GvdbItem *item;
-
- item = gvdb_hash_table_insert (parent, name_in_parent);
- gvdb_item_set_hash_table (item, table);
- }
-
- return table;
-}
-
-static guint32
-djb_hash (const gchar *key)
-{
- guint32 hash_value = 5381;
-
- while (*key)
- hash_value = hash_value * 33 + *(signed char *)key++;
-
- return hash_value;
-}
-
-GvdbItem *
-gvdb_hash_table_insert (GHashTable *table,
- const gchar *key)
-{
- GvdbItem *item;
-
- item = g_slice_new0 (GvdbItem);
- item->key = g_strdup (key);
- item->hash_value = djb_hash (key);
-
- g_hash_table_insert (table, g_strdup (key), item);
-
- return item;
-}
-
-void
-gvdb_hash_table_insert_string (GHashTable *table,
- const gchar *key,
- const gchar *value)
-{
- GvdbItem *item;
-
- item = gvdb_hash_table_insert (table, key);
- gvdb_item_set_value (item, g_variant_new_string (value));
-}
-
-void
-gvdb_item_set_value (GvdbItem *item,
- GVariant *value)
-{
- g_return_if_fail (!item->value && !item->table && !item->child);
-
- item->value = g_variant_ref_sink (value);
-}
-
-void
-gvdb_item_set_hash_table (GvdbItem *item,
- GHashTable *table)
-{
- g_return_if_fail (!item->value && !item->table && !item->child);
-
- item->table = g_hash_table_ref (table);
-}
-
-void
-gvdb_item_set_parent (GvdbItem *item,
- GvdbItem *parent)
-{
- GvdbItem **node;
-
- g_return_if_fail (g_str_has_prefix (item->key, parent->key));
- g_return_if_fail (!parent->value && !parent->table);
- g_return_if_fail (!item->parent && !item->sibling);
-
- for (node = &parent->child; *node; node = &(*node)->sibling)
- if (strcmp ((*node)->key, item->key) > 0)
- break;
-
- item->parent = parent;
- item->sibling = *node;
- *node = item;
-}
-
-typedef struct
-{
- GvdbItem **buckets;
- gint n_buckets;
-} HashTable;
-
-static HashTable *
-hash_table_new (gint n_buckets)
-{
- HashTable *table;
-
- table = g_slice_new (HashTable);
- table->buckets = g_new0 (GvdbItem *, n_buckets);
- table->n_buckets = n_buckets;
-
- return table;
-}
-
-static void
-hash_table_free (HashTable *table)
-{
- g_free (table->buckets);
-
- g_slice_free (HashTable, table);
-}
-
-static void
-hash_table_insert (gpointer key,
- gpointer value,
- gpointer data)
-{
- guint32 hash_value, bucket;
- HashTable *table = data;
- GvdbItem *item = value;
-
- hash_value = djb_hash (key);
- bucket = hash_value % table->n_buckets;
- item->next = table->buckets[bucket];
- table->buckets[bucket] = item;
-}
-
-static guint32_le
-item_to_index (GvdbItem *item)
-{
- if (item != NULL)
- return item->assigned_index;
-
- return guint32_to_le (-1u);
-}
-
-typedef struct
-{
- GQueue *chunks;
- guint64 offset;
- gboolean byteswap;
-} FileBuilder;
-
-typedef struct
-{
- gsize offset;
- gsize size;
- gpointer data;
-} FileChunk;
-
-static gpointer
-file_builder_allocate (FileBuilder *fb,
- guint alignment,
- gsize size,
- struct gvdb_pointer *pointer)
-{
- FileChunk *chunk;
-
- if (size == 0)
- return NULL;
-
- fb->offset += (-fb->offset) & (alignment - 1);
- chunk = g_slice_new (FileChunk);
- chunk->offset = fb->offset;
- chunk->size = size;
- chunk->data = g_malloc (size);
-
- pointer->start = guint32_to_le (fb->offset);
- fb->offset += size;
- pointer->end = guint32_to_le (fb->offset);
-
- g_queue_push_tail (fb->chunks, chunk);
-
- return chunk->data;
-}
-
-static void
-file_builder_add_value (FileBuilder *fb,
- GVariant *value,
- struct gvdb_pointer *pointer)
-{
- GVariant *variant, *normal;
- gpointer data;
- gsize size;
-
- if (fb->byteswap)
- {
- value = g_variant_byteswap (value);
- variant = g_variant_new_variant (value);
- g_variant_unref (value);
- }
- else
- variant = g_variant_new_variant (value);
-
- normal = g_variant_get_normal_form (variant);
- g_variant_unref (variant);
-
- size = g_variant_get_size (normal);
- data = file_builder_allocate (fb, 8, size, pointer);
- g_variant_store (normal, data);
- g_variant_unref (normal);
-}
-
-static void
-file_builder_add_string (FileBuilder *fb,
- const gchar *string,
- guint32_le *start,
- guint16_le *size)
-{
- FileChunk *chunk;
- gsize length;
-
- length = strlen (string);
-
- chunk = g_slice_new (FileChunk);
- chunk->offset = fb->offset;
- chunk->size = length;
- chunk->data = g_malloc (length);
- memcpy (chunk->data, string, length);
-
- *start = guint32_to_le (fb->offset);
- *size = guint16_to_le (length);
- fb->offset += length;
-
- g_queue_push_tail (fb->chunks, chunk);
-}
-
-static void
-file_builder_allocate_for_hash (FileBuilder *fb,
- gsize n_buckets,
- gsize n_items,
- guint bloom_shift,
- gsize n_bloom_words,
- guint32_le **bloom_filter,
- guint32_le **hash_buckets,
- struct gvdb_hash_item **hash_items,
- struct gvdb_pointer *pointer)
-{
- guint32_le bloom_hdr, table_hdr;
- guchar *data;
- gsize size;
-
- g_assert (n_bloom_words < (1u << 27));
-
- bloom_hdr = guint32_to_le (bloom_shift << 27 | n_bloom_words);
- table_hdr = guint32_to_le (n_buckets);
-
- size = sizeof bloom_hdr + sizeof table_hdr +
- n_bloom_words * sizeof (guint32_le) +
- n_buckets * sizeof (guint32_le) +
- n_items * sizeof (struct gvdb_hash_item);
-
- data = file_builder_allocate (fb, 4, size, pointer);
-
-#define chunk(s) (size -= (s), data += (s), data - (s))
- memcpy (chunk (sizeof bloom_hdr), &bloom_hdr, sizeof bloom_hdr);
- memcpy (chunk (sizeof table_hdr), &table_hdr, sizeof table_hdr);
- *bloom_filter = (guint32_le *) chunk (n_bloom_words * sizeof (guint32_le));
- *hash_buckets = (guint32_le *) chunk (n_buckets * sizeof (guint32_le));
- *hash_items = (struct gvdb_hash_item *) chunk (n_items *
- sizeof (struct gvdb_hash_item));
- g_assert (size == 0);
-#undef chunk
-
- memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le));
-
- /* NOTE - the code to actually fill in the bloom filter here is missing.
- * Patches welcome!
- *
- * http://en.wikipedia.org/wiki/Bloom_filter
- * http://0pointer.de/blog/projects/bloom.html
- */
-}
-
-static void
-file_builder_add_hash (FileBuilder *fb,
- GHashTable *table,
- struct gvdb_pointer *pointer)
-{
- guint32_le *buckets, *bloom_filter;
- struct gvdb_hash_item *items;
- HashTable *mytable;
- GvdbItem *item;
- guint32 index;
- gint bucket;
-
- mytable = hash_table_new (g_hash_table_size (table));
- g_hash_table_foreach (table, hash_table_insert, mytable);
- index = 0;
-
- for (bucket = 0; bucket < mytable->n_buckets; bucket++)
- for (item = mytable->buckets[bucket]; item; item = item->next)
- item->assigned_index = guint32_to_le (index++);
-
- file_builder_allocate_for_hash (fb, mytable->n_buckets, index, 5, 0,
- &bloom_filter, &buckets, &items, pointer);
-
- index = 0;
- for (bucket = 0; bucket < mytable->n_buckets; bucket++)
- {
- buckets[bucket] = guint32_to_le (index);
-
- for (item = mytable->buckets[bucket]; item; item = item->next)
- {
- struct gvdb_hash_item *entry = items++;
- const gchar *basename;
-
- g_assert (index == guint32_from_le (item->assigned_index));
- entry->hash_value = guint32_to_le (item->hash_value);
- entry->parent = item_to_index (item->parent);
- entry->unused = 0;
-
- if (item->parent != NULL)
- basename = item->key + strlen (item->parent->key);
- else
- basename = item->key;
-
- file_builder_add_string (fb, basename,
- &entry->key_start,
- &entry->key_size);
-
- if (item->value != NULL)
- {
- g_assert (item->child == NULL && item->table == NULL);
-
- file_builder_add_value (fb, item->value, &entry->value.pointer);
- entry->type = 'v';
- }
-
- if (item->child != NULL)
- {
- guint32 children = 0, i = 0;
- guint32_le *offsets;
- GvdbItem *child;
-
- g_assert (item->table == NULL);
-
- for (child = item->child; child; child = child->sibling)
- children++;
-
- offsets = file_builder_allocate (fb, 4, 4 * children,
- &entry->value.pointer);
- entry->type = 'L';
-
- for (child = item->child; child; child = child->sibling)
- offsets[i++] = child->assigned_index;
-
- g_assert (children == i);
- }
-
- if (item->table != NULL)
- {
- entry->type = 'H';
- file_builder_add_hash (fb, item->table, &entry->value.pointer);
- }
-
- index++;
- }
- }
-
- hash_table_free (mytable);
-}
-
-static FileBuilder *
-file_builder_new (gboolean byteswap)
-{
- FileBuilder *builder;
-
- builder = g_slice_new (FileBuilder);
- builder->chunks = g_queue_new ();
- builder->offset = sizeof (struct gvdb_header);
- builder->byteswap = byteswap;
-
- return builder;
-}
-
-static GString *
-file_builder_serialise (FileBuilder *fb,
- struct gvdb_pointer root)
-{
- struct gvdb_header header = { { 0, }, };
- GString *result;
-
- if (fb->byteswap)
- {
- header.signature[0] = GVDB_SWAPPED_SIGNATURE0;
- header.signature[1] = GVDB_SWAPPED_SIGNATURE1;
- }
- else
- {
- header.signature[0] = GVDB_SIGNATURE0;
- header.signature[1] = GVDB_SIGNATURE1;
- }
-
- result = g_string_new (NULL);
-
- header.root = root;
- g_string_append_len (result, (gpointer) &header, sizeof header);
-
- while (!g_queue_is_empty (fb->chunks))
- {
- FileChunk *chunk = g_queue_pop_head (fb->chunks);
-
- if (result->len != chunk->offset)
- {
- gchar zero[8] = { 0, };
-
- g_assert (chunk->offset > result->len);
- g_assert (chunk->offset - result->len < 8);
-
- g_string_append_len (result, zero, chunk->offset - result->len);
- g_assert (result->len == chunk->offset);
- }
-
- g_string_append_len (result, chunk->data, chunk->size);
- g_free (chunk->data);
-
- g_slice_free (FileChunk, chunk);
- }
-
- g_queue_free (fb->chunks);
- g_slice_free (FileBuilder, fb);
-
- return result;
-}
-
-GBytes *
-gvdb_table_get_content (GHashTable *table,
- gboolean byteswap)
-{
- struct gvdb_pointer root;
- FileBuilder *fb;
- GString *str;
- GBytes *res;
-
- fb = file_builder_new (byteswap);
- file_builder_add_hash (fb, table, &root);
- str = file_builder_serialise (fb, root);
-
- res = g_bytes_new_take (str->str, str->len);
- g_string_free (str, FALSE);
-
- return res;
-}
-
-gboolean
-gvdb_table_write_contents (GHashTable *table,
- const gchar *filename,
- gboolean byteswap,
- GError **error)
-{
- GBytes *content;
- gboolean status;
-
- content = gvdb_table_get_content (table, byteswap);
-
- status = g_file_set_contents (filename, g_bytes_get_data (content, NULL), g_bytes_get_size (content), error);
-
- g_bytes_unref (content);
-
- return status;
-}
diff --git a/common/gvdb/gvdb-builder.h b/common/gvdb/gvdb-builder.h
deleted file mode 100644
index ad361dc6..00000000
--- a/common/gvdb/gvdb-builder.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright © 2010 Codethink Limited
- *
- * 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 of the licence, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#ifndef __gvdb_builder_h__
-#define __gvdb_builder_h__
-
-#include <gio/gio.h>
-
-typedef struct _GvdbItem GvdbItem;
-
-G_GNUC_INTERNAL
-GHashTable * gvdb_hash_table_new (GHashTable *parent,
- const gchar *key);
-
-G_GNUC_INTERNAL
-GvdbItem * gvdb_hash_table_insert (GHashTable *table,
- const gchar *key);
-G_GNUC_INTERNAL
-void gvdb_hash_table_insert_string (GHashTable *table,
- const gchar *key,
- const gchar *value);
-
-G_GNUC_INTERNAL
-void gvdb_item_set_value (GvdbItem *item,
- GVariant *value);
-G_GNUC_INTERNAL
-void gvdb_item_set_hash_table (GvdbItem *item,
- GHashTable *table);
-G_GNUC_INTERNAL
-void gvdb_item_set_parent (GvdbItem *item,
- GvdbItem *parent);
-
-G_GNUC_INTERNAL
-gboolean gvdb_table_write_contents (GHashTable *table,
- const gchar *filename,
- gboolean byteswap,
- GError **error);
-
-G_GNUC_INTERNAL
-GBytes * gvdb_table_get_content (GHashTable *table,
- gboolean byteswap);
-
-
-#endif /* __gvdb_builder_h__ */
diff --git a/common/gvdb/gvdb-format.h b/common/gvdb/gvdb-format.h
deleted file mode 100644
index 486e8547..00000000
--- a/common/gvdb/gvdb-format.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright © 2010 Codethink Limited
- *
- * 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 of the licence, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#ifndef __gvdb_format_h__
-#define __gvdb_format_h__
-
-#include <glib.h>
-
-typedef struct { guint16 value; } guint16_le;
-typedef struct { guint32 value; } guint32_le;
-
-struct gvdb_pointer {
- guint32_le start;
- guint32_le end;
-};
-
-struct gvdb_hash_header {
- guint32_le n_bloom_words;
- guint32_le n_buckets;
-};
-
-struct gvdb_hash_item {
- guint32_le hash_value;
- guint32_le parent;
-
- guint32_le key_start;
- guint16_le key_size;
- gchar type;
- gchar unused;
-
- union
- {
- struct gvdb_pointer pointer;
- gchar direct[8];
- } value;
-};
-
-struct gvdb_header {
- guint32 signature[2];
- guint32_le version;
- guint32_le options;
-
- struct gvdb_pointer root;
-};
-
-static inline guint32_le guint32_to_le (guint32 value) {
- guint32_le result = { GUINT32_TO_LE (value) };
- return result;
-}
-
-static inline guint32 guint32_from_le (guint32_le value) {
- return GUINT32_FROM_LE (value.value);
-}
-
-static inline guint16_le guint16_to_le (guint16 value) {
- guint16_le result = { GUINT16_TO_LE (value) };
- return result;
-}
-
-static inline guint16 guint16_from_le (guint16_le value) {
- return GUINT16_FROM_LE (value.value);
-}
-
-#define GVDB_SIGNATURE0 1918981703
-#define GVDB_SIGNATURE1 1953390953
-#define GVDB_SWAPPED_SIGNATURE0 GUINT32_SWAP_LE_BE (GVDB_SIGNATURE0)
-#define GVDB_SWAPPED_SIGNATURE1 GUINT32_SWAP_LE_BE (GVDB_SIGNATURE1)
-
-#endif /* __gvdb_format_h__ */
diff --git a/common/gvdb/gvdb-reader.c b/common/gvdb/gvdb-reader.c
deleted file mode 100644
index 08b5bc8c..00000000
--- a/common/gvdb/gvdb-reader.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * Copyright © 2010 Codethink Limited
- *
- * 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 of the licence, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#include "gvdb-reader.h"
-#include "gvdb-format.h"
-
-#include <string.h>
-
-struct _GvdbTable {
- GBytes *bytes;
-
- const gchar *data;
- gsize size;
-
- gboolean byteswapped;
- gboolean trusted;
-
- const guint32_le *bloom_words;
- guint32 n_bloom_words;
- guint bloom_shift;
-
- const guint32_le *hash_buckets;
- guint32 n_buckets;
-
- struct gvdb_hash_item *hash_items;
- guint32 n_hash_items;
-};
-
-static const gchar *
-gvdb_table_item_get_key (GvdbTable *file,
- const struct gvdb_hash_item *item,
- gsize *size)
-{
- guint32 start, end;
-
- start = guint32_from_le (item->key_start);
- *size = guint16_from_le (item->key_size);
- end = start + *size;
-
- if G_UNLIKELY (start > end || end > file->size)
- return NULL;
-
- return file->data + start;
-}
-
-static gconstpointer
-gvdb_table_dereference (GvdbTable *file,
- const struct gvdb_pointer *pointer,
- gint alignment,
- gsize *size)
-{
- guint32 start, end;
-
- start = guint32_from_le (pointer->start);
- end = guint32_from_le (pointer->end);
-
- if G_UNLIKELY (start > end || end > file->size || start & (alignment - 1))
- return NULL;
-
- *size = end - start;
-
- return file->data + start;
-}
-
-static void
-gvdb_table_setup_root (GvdbTable *file,
- const struct gvdb_pointer *pointer)
-{
- const struct gvdb_hash_header *header;
- guint32 n_bloom_words;
- guint32 n_buckets;
- gsize size;
-
- header = gvdb_table_dereference (file, pointer, 4, &size);
-
- if G_UNLIKELY (header == NULL || size < sizeof *header)
- return;
-
- size -= sizeof *header;
-
- n_bloom_words = guint32_from_le (header->n_bloom_words);
- n_buckets = guint32_from_le (header->n_buckets);
- n_bloom_words &= (1u << 27) - 1;
-
- if G_UNLIKELY (n_bloom_words * sizeof (guint32_le) > size)
- return;
-
- file->bloom_words = (gpointer) (header + 1);
- size -= n_bloom_words * sizeof (guint32_le);
- file->n_bloom_words = n_bloom_words;
-
- if G_UNLIKELY (n_buckets > G_MAXUINT / sizeof (guint32_le) ||
- n_buckets * sizeof (guint32_le) > size)
- return;
-
- file->hash_buckets = file->bloom_words + file->n_bloom_words;
- size -= n_buckets * sizeof (guint32_le);
- file->n_buckets = n_buckets;
-
- if G_UNLIKELY (size % sizeof (struct gvdb_hash_item))
- return;
-
- file->hash_items = (gpointer) (file->hash_buckets + n_buckets);
- file->n_hash_items = size / sizeof (struct gvdb_hash_item);
-}
-
-/**
- * gvdb_table_new_from_bytes:
- * @bytes: the #GBytes with the data
- * @trusted: if the contents of @bytes are trusted
- * @error: %NULL, or a pointer to a %NULL #GError
- * @returns: a new #GvdbTable
- *
- * Creates a new #GvdbTable from the contents of @bytes.
- *
- * This call can fail if the header contained in @bytes is invalid.
- *
- * You should call gvdb_table_free() on the return result when you no
- * longer require it.
- **/
-GvdbTable *
-gvdb_table_new_from_bytes (GBytes *bytes,
- gboolean trusted,
- GError **error)
-{
- const struct gvdb_header *header;
- GvdbTable *file;
-
- file = g_slice_new0 (GvdbTable);
- file->bytes = g_bytes_ref (bytes);
- file->data = g_bytes_get_data (bytes, &file->size);
- file->trusted = trusted;
-
- if (file->size < sizeof (struct gvdb_header))
- goto invalid;
-
- header = (gpointer) file->data;
-
- if (header->signature[0] == GVDB_SIGNATURE0 &&
- header->signature[1] == GVDB_SIGNATURE1 &&
- guint32_from_le (header->version) == 0)
- file->byteswapped = FALSE;
-
- else if (header->signature[0] == GVDB_SWAPPED_SIGNATURE0 &&
- header->signature[1] == GVDB_SWAPPED_SIGNATURE1 &&
- guint32_from_le (header->version) == 0)
- file->byteswapped = TRUE;
-
- else
- goto invalid;
-
- gvdb_table_setup_root (file, &header->root);
-
- return file;
-
-invalid:
- g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "invalid gvdb header");
-
- g_bytes_unref (file->bytes);
-
- g_slice_free (GvdbTable, file);
-
- return NULL;
-}
-
-/**
- * gvdb_table_new:
- * @filename: a filename
- * @trusted: if the contents of @bytes are trusted
- * @error: %NULL, or a pointer to a %NULL #GError
- * @returns: a new #GvdbTable
- *
- * Creates a new #GvdbTable using the #GMappedFile for @filename as the
- * #GBytes.
- **/
-GvdbTable *
-gvdb_table_new (const gchar *filename,
- gboolean trusted,
- GError **error)
-{
- GMappedFile *mapped;
- GvdbTable *table;
- GBytes *bytes;
-
- mapped = g_mapped_file_new (filename, FALSE, error);
- if (!mapped)
- return NULL;
-
- bytes = g_mapped_file_get_bytes (mapped);
- table = gvdb_table_new_from_bytes (bytes, trusted, error);
- g_mapped_file_unref (mapped);
- g_bytes_unref (bytes);
-
- g_prefix_error (error, "%s: ", filename);
-
- return table;
-}
-
-static gboolean
-gvdb_table_bloom_filter (GvdbTable *file,
- guint32 hash_value)
-{
- guint32 word, mask;
-
- if (file->n_bloom_words == 0)
- return TRUE;
-
- word = (hash_value / 32) % file->n_bloom_words;
- mask = 1 << (hash_value & 31);
- mask |= 1 << ((hash_value >> file->bloom_shift) & 31);
-
- return (guint32_from_le (file->bloom_words[word]) & mask) == mask;
-}
-
-static gboolean
-gvdb_table_check_name (GvdbTable *file,
- struct gvdb_hash_item *item,
- const gchar *key,
- guint key_length)
-{
- const gchar *this_key;
- gsize this_size;
- guint32 parent;
-
- this_key = gvdb_table_item_get_key (file, item, &this_size);
-
- if G_UNLIKELY (this_key == NULL || this_size > key_length)
- return FALSE;
-
- key_length -= this_size;
-
- if G_UNLIKELY (memcmp (this_key, key + key_length, this_size) != 0)
- return FALSE;
-
- parent = guint32_from_le (item->parent);
- if (key_length == 0 && parent == 0xffffffffu)
- return TRUE;
-
- if G_LIKELY (parent < file->n_hash_items && this_size > 0)
- return gvdb_table_check_name (file,
- &file->hash_items[parent],
- key, key_length);
-
- return FALSE;
-}
-
-static const struct gvdb_hash_item *
-gvdb_table_lookup (GvdbTable *file,
- const gchar *key,
- gchar type)
-{
- guint32 hash_value = 5381;
- guint key_length;
- guint32 bucket;
- guint32 lastno;
- guint32 itemno;
-
- if G_UNLIKELY (file->n_buckets == 0 || file->n_hash_items == 0)
- return NULL;
-
- for (key_length = 0; key[key_length]; key_length++)
- hash_value = (hash_value * 33) + ((signed char *) key)[key_length];
-
- if (!gvdb_table_bloom_filter (file, hash_value))
- return NULL;
-
- bucket = hash_value % file->n_buckets;
- itemno = guint32_from_le (file->hash_buckets[bucket]);
-
- if (bucket == file->n_buckets - 1 ||
- (lastno = guint32_from_le(file->hash_buckets[bucket + 1])) > file->n_hash_items)
- lastno = file->n_hash_items;
-
- while G_LIKELY (itemno < lastno)
- {
- struct gvdb_hash_item *item = &file->hash_items[itemno];
-
- if (hash_value == guint32_from_le (item->hash_value))
- if G_LIKELY (gvdb_table_check_name (file, item, key, key_length))
- if G_LIKELY (item->type == type)
- return item;
-
- itemno++;
- }
-
- return NULL;
-}
-
-static gboolean
-gvdb_table_list_from_item (GvdbTable *table,
- const struct gvdb_hash_item *item,
- const guint32_le **list,
- guint *length)
-{
- gsize size;
-
- *list = gvdb_table_dereference (table, &item->value.pointer, 4, &size);
-
- if G_LIKELY (*list == NULL || size % 4)
- return FALSE;
-
- *length = size / 4;
-
- return TRUE;
-}
-
-/**
- * gvdb_table_get_names:
- * @table: a #GvdbTable
- * @length: the number of items returned, or %NULL
- *
- * Gets a list of all names contained in @table.
- *
- * No call to gvdb_table_get_table(), gvdb_table_list() or
- * gvdb_table_get_value() will succeed unless it is for one of the
- * names returned by this function.
- *
- * Note that some names that are returned may still fail for all of the
- * above calls in the case of the corrupted file. Note also that the
- * returned strings may not be utf8.
- *
- * Returns: a %NULL-terminated list of strings, of length @length
- **/
-gchar **
-gvdb_table_get_names (GvdbTable *table,
- gint *length)
-{
- gchar **names;
- gint n_names;
- gint filled;
- gint total;
- gint i;
-
- /* We generally proceed by iterating over the list of items in the
- * hash table (in order of appearance) recording them into an array.
- *
- * Each item has a parent item (except root items). The parent item
- * forms part of the name of the item. We could go fetching the
- * parent item chain at the point that we encounter each item but then
- * we would need to implement some sort of recursion along with checks
- * for self-referential items.
- *
- * Instead, we do a number of passes. Each pass will build up one
- * level of names (starting from the root). We continue to do passes
- * until no more items are left. The first pass will only add root
- * items and each further pass will only add items whose direct parent
- * is an item added in the immediately previous pass. It's also
- * possible that items get filled if they follow their parent within a
- * particular pass.
- *
- * At most we will have a number of passes equal to the depth of the
- * tree. Self-referential items will never be filled in (since their
- * parent will have never been filled in). We continue until we have
- * a pass that fills in no additional items.
- *
- * This takes an O(n) algorithm and turns it into O(n*m) where m is
- * the depth of the tree, but in all sane cases the tree won't be very
- * deep and the constant factor of this algorithm is lower (and the
- * complexity of coding it, as well).
- */
-
- n_names = table->n_hash_items;
- names = g_new0 (gchar *, n_names + 1);
-
- /* 'names' starts out all-NULL. On each pass we record the number
- * of items changed from NULL to non-NULL in 'filled' so we know if we
- * should repeat the loop. 'total' counts the total number of items
- * filled. If 'total' ends up equal to 'n_names' then we know that
- * 'names' has been completely filled.
- */
-
- total = 0;
- do
- {
- /* Loop until we have filled no more entries */
- filled = 0;
-
- for (i = 0; i < n_names; i++)
- {
- const struct gvdb_hash_item *item = &table->hash_items[i];
- const gchar *name;
- gsize name_length;
- guint32 parent;
-
- /* already got it on a previous pass */
- if (names[i] != NULL)
- continue;
-
- parent = guint32_from_le (item->parent);
-
- if (parent == 0xffffffffu)
- {
- /* it's a root item */
- name = gvdb_table_item_get_key (table, item, &name_length);
-
- if (name != NULL)
- {
- names[i] = g_strndup (name, name_length);
- filled++;
- }
- }
-
- else if (parent < n_names && names[parent] != NULL)
- {
- /* It's a non-root item whose parent was filled in already.
- *
- * Calculate the name of this item by combining it with
- * its parent name.
- */
- name = gvdb_table_item_get_key (table, item, &name_length);
-
- if (name != NULL)
- {
- const gchar *parent_name = names[parent];
- gsize parent_length;
- gchar *fullname;
-
- parent_length = strlen (parent_name);
- fullname = g_malloc (parent_length + name_length + 1);
- memcpy (fullname, parent_name, parent_length);
- memcpy (fullname + parent_length, name, name_length);
- fullname[parent_length + name_length] = '\0';
- names[i] = fullname;
- filled++;
- }
- }
- }
-
- total += filled;
- }
- while (filled && total < n_names);
-
- /* If the table was corrupted then 'names' may have holes in it.
- * Collapse those.
- */
- if G_UNLIKELY (total != n_names)
- {
- GPtrArray *fixed_names;
-
- fixed_names = g_ptr_array_new ();
- for (i = 0; i < n_names; i++)
- if (names[i] != NULL)
- g_ptr_array_add (fixed_names, names[i]);
-
- g_free (names);
- n_names = fixed_names->len;
- g_ptr_array_add (fixed_names, NULL);
- names = (gchar **) g_ptr_array_free (fixed_names, FALSE);
- }
-
- if (length)
- *length = n_names;
-
- return names;
-}
-
-/**
- * gvdb_table_list:
- * @file: a #GvdbTable
- * @key: a string
- * @returns: a %NULL-terminated string array
- *
- * List all of the keys that appear below @key. The nesting of keys
- * within the hash file is defined by the program that created the hash
- * file. One thing is constant: each item in the returned array can be
- * concatenated to @key to obtain the full name of that key.
- *
- * It is not possible to tell from this function if a given key is
- * itself a path, a value, or another hash table; you are expected to
- * know this for yourself.
- *
- * You should call g_strfreev() on the return result when you no longer
- * require it.
- **/
-gchar **
-gvdb_table_list (GvdbTable *file,
- const gchar *key)
-{
- const struct gvdb_hash_item *item;
- const guint32_le *list;
- gchar **strv;
- guint length;
- guint i;
-
- if ((item = gvdb_table_lookup (file, key, 'L')) == NULL)
- return NULL;
-
- if (!gvdb_table_list_from_item (file, item, &list, &length))
- return NULL;
-
- strv = g_new (gchar *, length + 1);
- for (i = 0; i < length; i++)
- {
- guint32 itemno = guint32_from_le (list[i]);
-
- if (itemno < file->n_hash_items)
- {
- const struct gvdb_hash_item *item;
- const gchar *string;
- gsize strsize;
-
- item = file->hash_items + itemno;
-
- string = gvdb_table_item_get_key (file, item, &strsize);
-
- if (string != NULL)
- strv[i] = g_strndup (string, strsize);
- else
- strv[i] = g_malloc0 (1);
- }
- else
- strv[i] = g_malloc0 (1);
- }
-
- strv[i] = NULL;
-
- return strv;
-}
-
-/**
- * gvdb_table_has_value:
- * @file: a #GvdbTable
- * @key: a string
- * @returns: %TRUE if @key is in the table
- *
- * Checks for a value named @key in @file.
- *
- * Note: this function does not consider non-value nodes (other hash
- * tables, for example).
- **/
-gboolean
-gvdb_table_has_value (GvdbTable *file,
- const gchar *key)
-{
- static const struct gvdb_hash_item *item;
- gsize size;
-
- item = gvdb_table_lookup (file, key, 'v');
-
- if (item == NULL)
- return FALSE;
-
- return gvdb_table_dereference (file, &item->value.pointer, 8, &size) != NULL;
-}
-
-static GVariant *
-gvdb_table_value_from_item (GvdbTable *table,
- const struct gvdb_hash_item *item)
-{
- GVariant *variant, *value;
- gconstpointer data;
- GBytes *bytes;
- gsize size;
-
- data = gvdb_table_dereference (table, &item->value.pointer, 8, &size);
-
- if G_UNLIKELY (data == NULL)
- return NULL;
-
- bytes = g_bytes_new_from_bytes (table->bytes, ((gchar *) data) - table->data, size);
- variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT, bytes, table->trusted);
- value = g_variant_get_variant (variant);
- g_variant_unref (variant);
- g_bytes_unref (bytes);
-
- return value;
-}
-
-/**
- * gvdb_table_get_value:
- * @file: a #GvdbTable
- * @key: a string
- * @returns: a #GVariant, or %NULL
- *
- * Looks up a value named @key in @file.
- *
- * If the value is not found then %NULL is returned. Otherwise, a new
- * #GVariant instance is returned. The #GVariant does not depend on the
- * continued existence of @file.
- *
- * You should call g_variant_unref() on the return result when you no
- * longer require it.
- **/
-GVariant *
-gvdb_table_get_value (GvdbTable *file,
- const gchar *key)
-{
- const struct gvdb_hash_item *item;
- GVariant *value;
-
- if ((item = gvdb_table_lookup (file, key, 'v')) == NULL)
- return NULL;
-
- value = gvdb_table_value_from_item (file, item);
-
- if (value && file->byteswapped)
- {
- GVariant *tmp;
-
- tmp = g_variant_byteswap (value);
- g_variant_unref (value);
- value = tmp;
- }
-
- return value;
-}
-
-/**
- * gvdb_table_get_raw_value:
- * @table: a #GvdbTable
- * @key: a string
- * @returns: a #GVariant, or %NULL
- *
- * Looks up a value named @key in @file.
- *
- * This call is equivalent to gvdb_table_get_value() except that it
- * never byteswaps the value.
- **/
-GVariant *
-gvdb_table_get_raw_value (GvdbTable *table,
- const gchar *key)
-{
- const struct gvdb_hash_item *item;
-
- if ((item = gvdb_table_lookup (table, key, 'v')) == NULL)
- return NULL;
-
- return gvdb_table_value_from_item (table, item);
-}
-
-/**
- * gvdb_table_get_table:
- * @file: a #GvdbTable
- * @key: a string
- * @returns: a new #GvdbTable, or %NULL
- *
- * Looks up the hash table named @key in @file.
- *
- * The toplevel hash table in a #GvdbTable can contain reference to
- * child hash tables (and those can contain further references...).
- *
- * If @key is not found in @file then %NULL is returned. Otherwise, a
- * new #GvdbTable is returned, referring to the child hashtable as
- * contained in the file. This newly-created #GvdbTable does not depend
- * on the continued existence of @file.
- *
- * You should call gvdb_table_free() on the return result when you no
- * longer require it.
- **/
-GvdbTable *
-gvdb_table_get_table (GvdbTable *file,
- const gchar *key)
-{
- const struct gvdb_hash_item *item;
- GvdbTable *new;
-
- item = gvdb_table_lookup (file, key, 'H');
-
- if (item == NULL)
- return NULL;
-
- new = g_slice_new0 (GvdbTable);
- new->bytes = g_bytes_ref (file->bytes);
- new->byteswapped = file->byteswapped;
- new->trusted = file->trusted;
- new->data = file->data;
- new->size = file->size;
-
- gvdb_table_setup_root (new, &item->value.pointer);
-
- return new;
-}
-
-/**
- * gvdb_table_free:
- * @file: a #GvdbTable
- *
- * Frees @file.
- **/
-void
-gvdb_table_free (GvdbTable *file)
-{
- g_bytes_unref (file->bytes);
- g_slice_free (GvdbTable, file);
-}
-
-/**
- * gvdb_table_is_valid:
- * @table: a #GvdbTable
- * @returns: %TRUE if @table is still valid
- *
- * Checks if the table is still valid.
- *
- * An on-disk GVDB can be marked as invalid. This happens when the file
- * has been replaced. The appropriate action is typically to reopen the
- * file.
- **/
-gboolean
-gvdb_table_is_valid (GvdbTable *table)
-{
- return !!*table->data;
-}
diff --git a/common/gvdb/gvdb-reader.h b/common/gvdb/gvdb-reader.h
deleted file mode 100644
index 241b41ae..00000000
--- a/common/gvdb/gvdb-reader.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010 Codethink Limited
- *
- * 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 of the licence, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#ifndef __gvdb_reader_h__
-#define __gvdb_reader_h__
-
-#include <glib.h>
-
-typedef struct _GvdbTable GvdbTable;
-
-G_BEGIN_DECLS
-
-G_GNUC_INTERNAL
-GvdbTable * gvdb_table_new_from_bytes (GBytes *bytes,
- gboolean trusted,
- GError **error);
-G_GNUC_INTERNAL
-GvdbTable * gvdb_table_new (const gchar *filename,
- gboolean trusted,
- GError **error);
-G_GNUC_INTERNAL
-void gvdb_table_free (GvdbTable *table);
-G_GNUC_INTERNAL
-gchar ** gvdb_table_get_names (GvdbTable *table,
- gint *length);
-G_GNUC_INTERNAL
-gchar ** gvdb_table_list (GvdbTable *table,
- const gchar *key);
-G_GNUC_INTERNAL
-GvdbTable * gvdb_table_get_table (GvdbTable *table,
- const gchar *key);
-G_GNUC_INTERNAL
-GVariant * gvdb_table_get_raw_value (GvdbTable *table,
- const gchar *key);
-G_GNUC_INTERNAL
-GVariant * gvdb_table_get_value (GvdbTable *table,
- const gchar *key);
-
-G_GNUC_INTERNAL
-gboolean gvdb_table_has_value (GvdbTable *table,
- const gchar *key);
-G_GNUC_INTERNAL
-gboolean gvdb_table_is_valid (GvdbTable *table);
-
-G_END_DECLS
-
-#endif /* __gvdb_reader_h__ */
diff --git a/common/gvdb/gvdb.doap b/common/gvdb/gvdb.doap
deleted file mode 100644
index b4ae60c8..00000000
--- a/common/gvdb/gvdb.doap
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-
-<Project xmlns='http://usefulinc.com/ns/doap#'
- xmlns:foaf='http://xmlns.com/foaf/0.1/'
- xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
- xmlns:gnome='http://api.gnome.org/doap-extensions#'>
-
- <name xml:lang='en'>gvdb</name>
- <shortdesc xml:lang='en'>GVariant Database file</shortdesc>
- <description xml:lang='en'>
- A simple database file format that stores a mapping from strings to
- GVariant values in a way that is extremely efficient for lookups.
-
- The database is written once and can not be modified.
-
- Included here is reader code and a first-pass implementation of a
- writer (that does not currently produce particularly optimised
- output).
-
- It is intended that this code be used by copy-pasting into your
- project or by making use of git-merge(1).
- </description>
-
- <maintainer>
- <foaf:Person>
- <foaf:name>Ryan Lortie</foaf:name>
- <foaf:mbox rdf:resource='mailto:desrt@desrt.ca'/>
- <gnome:userid>ryanl</gnome:userid>
- </foaf:Person>
- </maintainer>
-
-</Project>
diff --git a/data/Makefile.am.inc b/data/Makefile.am.inc
index 71e514e6..9bfe6782 100644
--- a/data/Makefile.am.inc
+++ b/data/Makefile.am.inc
@@ -1,13 +1,10 @@
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \
- data/org.freedesktop.impl.portal.PermissionStore.xml \
- data/org.freedesktop.portal.Documents.xml \
data/org.freedesktop.Flatpak.xml \
$(NULL)
EXTRA_DIST += \
data/org.freedesktop.portal.Documents.xml \
- data/org.freedesktop.impl.portal.PermissionStore.xml \
data/org.freedesktop.systemd1.xml \
data/org.freedesktop.Flatpak.xml \
$(NULL)
diff --git a/data/org.freedesktop.impl.portal.PermissionStore.xml b/data/org.freedesktop.impl.portal.PermissionStore.xml
deleted file mode 100644
index 0e59e386..00000000
--- a/data/org.freedesktop.impl.portal.PermissionStore.xml
+++ /dev/null
@@ -1,163 +0,0 @@
-<!DOCTYPE node PUBLIC
-"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
-"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-
-<!--
- Copyright (C) 2015 Red Hat, Inc.
-
- 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 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
- Author: Alexander Larsson <alexl@redhat.com>
--->
-
-<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
- <!--
- org.freedesktop.impl.portal.PermissionStore:
- @short_description: Database to store permissions
-
- The permission store can be used by portals to store permissions
- that sandboxed applications have to various resources, such as
- files outside the sandbox.
-
- Since the resources managed by portals can be varied, the permission
- store is fairly free-form: there can be multiple tables; resources are
- identified by an ID, as are applications, and permissions are stored as
- string arrays. None of these strings are interpreted by the permission
- store in any way.
-
- In addition, the permission store allows to associate extra data
- (in the form of a GVariant) with each resource.
- -->
- <interface name='org.freedesktop.impl.portal.PermissionStore'>
- <property name="version" type="u" access="read"/>
-
- <!--
- Lookup:
- @table: the name of the table to use
- @id: the resource ID to look up
- @permissions: map from application ID to permissions
- @data: data that is associated with the resource
-
- Looks up the entry for a resource in one of the tables and returns
- all associated application permissions and data.
- -->
- <method name="Lookup">
- <arg name='table' type='s' direction='in'/>
- <arg name='id' type='s' direction='in'/>
- <arg name='permissions' type='a{sas}' direction='out'/>
- <arg name='data' type='v' direction='out'/>
- </method>
-
- <!--
- Set:
- @table: the name of the table to use
- @create: whether to create the table if it does not exist
- @id: the resource ID to modify
- @app_permissions: map from application ID to permissions
- @data: data to associate with the resource
-
- Writes the entry for a resource in the given table.
- -->
- <method name="Set">
- <arg name='table' type='s' direction='in'/>
- <arg name='create' type='b' direction='in'/>
- <arg name='id' type='s' direction='in'/>
- <arg name='app_permissions' type='a{sas}' direction='in'/>
- <arg name='data' type='v' direction='in'/>
- </method>
-
- <!--
- Delete:
- @table: the name of the table to use
- @id: the resource ID to delete
-
- Removes the entry for a resource in the given table.
- -->
- <method name="Delete">
- <arg name='table' type='s' direction='in'/>
- <arg name='id' type='s' direction='in'/>
- </method>
-
- <!--
- SetValue:
- @table: the name of the table to use
- @create: whether to create the table if it does not exist
- @id: the resource ID to modify
- @data: data to associate with the resource
-
- Sets just the data for a resource in the given table.
- -->
- <method name="SetValue">
- <arg name='table' type='s' direction='in'/>
- <arg name='create' type='b' direction='in'/>
- <arg name='id' type='s' direction='in'/>
- <arg name='data' type='v' direction='in'/>
- </method>
-
- <!--
- SetPermission:
- @table: the name of the table to use
- @create: whether to create the table if it does not exist
- @id: the resource ID to modify
- @app: the application ID to modify
- @permissions: permissions to set
-
- Sets the permissions for an application and a resource
- in the given table.
- -->
- <method name="SetPermission">
- <arg name='table' type='s' direction='in'/>
- <arg name='create' type='b' direction='in'/>
- <arg name='id' type='s' direction='in'/>
- <arg name='app' type='s' direction='in'/>
- <arg name='permissions' type='as' direction='in'/>
- </method>
-
- <!--
- List:
- @table: the name of the table to use
- @ids: IDs of all resources that are present in the table
-
- Returns all the resources that are present in the table.
- -->
- <method name="List">
- <arg name='table' type='s' direction='in'/>
- <arg name='ids' type='as' direction='out'/>
- </method>
-
- <!--
- Changed:
- @table: the name of the table
- @ids: IDs of the changed resource
- @deleted: whether the resource was deleted
- @data: the data that is associated the resource
- @permissions: the permissions that are associated with the resource
-
- The Changed signal is emitted when the entry for a resource
- is modified or deleted. If the entry was deleted, then @data
- and @permissions contain the last values that were found in the
- database. If the entry was modified, they contain the new values.
- -->
- <signal name="Changed">
- <arg name='table' type='s' direction='out'/>
- <arg name='id' type='s' direction='out'/>
- <arg name='deleted' type='b' direction='out'/>
- <arg name='data' type='v' direction='out'/>
- <arg name='permissions' type='a{sas}' direction='out'/>
- </signal>
- </interface>
-
-</node>
diff --git a/document-portal/Makefile.am.inc b/document-portal/Makefile.am.inc
deleted file mode 100644
index f011ccdf..00000000
--- a/document-portal/Makefile.am.inc
+++ /dev/null
@@ -1,43 +0,0 @@
-libexec_PROGRAMS += \
- xdg-document-portal \
- $(NULL)
-
-xdp_dbus_built_sources = document-portal/xdp-dbus.c document-portal/xdp-dbus.h
-BUILT_SOURCES += $(xdp_dbus_built_sources)
-
-document-portal/xdp-dbus.c: data/org.freedesktop.portal.Documents.xml Makefile
- mkdir -p $(builddir)/document-portal
- $(AM_V_GEN) $(GDBUS_CODEGEN) \
- --interface-prefix org.freedesktop.portal. \
- --c-namespace XdpDbus \
- --generate-c-code $(builddir)/document-portal/xdp-dbus \
- --annotate "org.freedesktop.portal.Documents.Add()" org.gtk.GDBus.C.UnixFD "yes" \
- --annotate "org.freedesktop.portal.Documents.AddFull()" org.gtk.GDBus.C.UnixFD "yes" \
- $(srcdir)/data/org.freedesktop.portal.Documents.xml \
- $(NULL)
-
-document-portal/%-dbus.h: document-portal/%-dbus.c
- @true # Built as a side-effect of the rules for the .c
-
-service_in_files += document-portal/xdg-document-portal.service.in
-systemduserunit_DATA += document-portal/xdg-document-portal.service
-
-service_in_files += document-portal/org.freedesktop.portal.Documents.service.in
-dbus_service_DATA += document-portal/org.freedesktop.portal.Documents.service
-
-nodist_xdg_document_portal_SOURCES = \
- $(xdp_dbus_built_sources) \
- $(ps_dbus_built_sources) \
- $(NULL)
-
-xdg_document_portal_SOURCES = \
- document-portal/xdp-main.c \
- document-portal/xdp-enums.h \
- document-portal/xdp-util.h \
- document-portal/xdp-util.c \
- document-portal/xdp-fuse.h \
- document-portal/xdp-fuse.c \
- $(NULL)
-
-xdg_document_portal_LDADD = $(AM_LDADD) $(BASE_LIBS) $(FUSE_LIBS) libflatpak-common.la
-xdg_document_portal_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) $(FUSE_CFLAGS) -I$(srcdir)/document-portal -I$(builddir)/document-portal -I$(srcdir)/permission-store -I$(builddir)/permission-store -DFLATPAK_COMPILATION
diff --git a/document-portal/org.freedesktop.portal.Documents.service.in b/document-portal/org.freedesktop.portal.Documents.service.in
deleted file mode 100644
index cf0c1efc..00000000
--- a/document-portal/org.freedesktop.portal.Documents.service.in
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=org.freedesktop.portal.Documents
-Exec=@libexecdir@/xdg-document-portal
-SystemdService=xdg-document-portal.service
diff --git a/document-portal/xdg-document-portal.service.in b/document-portal/xdg-document-portal.service.in
deleted file mode 100644
index 66f9cbd7..00000000
--- a/document-portal/xdg-document-portal.service.in
+++ /dev/null
@@ -1,7 +0,0 @@
-[Unit]
-Description=flatpak document portal service
-
-[Service]
-BusName=org.freedesktop.portal.Documents
-ExecStart=@libexecdir@/xdg-document-portal
-Type=dbus
diff --git a/document-portal/xdp-enums.h b/document-portal/xdp-enums.h
deleted file mode 100644
index f9cd223d..00000000
--- a/document-portal/xdp-enums.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef XDP_ENUMS_H
-#define XDP_ENUMS_H
-
-G_BEGIN_DECLS
-
-typedef enum {
- XDP_PERMISSION_FLAGS_READ = (1 << 0),
- XDP_PERMISSION_FLAGS_WRITE = (1 << 1),
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS = (1 << 2),
- XDP_PERMISSION_FLAGS_DELETE = (1 << 3),
-
- XDP_PERMISSION_FLAGS_ALL = ((1 << 4) - 1)
-} XdpPermissionFlags;
-
-typedef enum {
- XDP_ADD_FLAGS_REUSE_EXISTING = (1 << 0),
- XDP_ADD_FLAGS_PERSISTENT = (1 << 1),
- XDP_ADD_FLAGS_AS_NEEDED_BY_APP = (1 << 2),
-
- XDP_ADD_FLAGS_FLAGS_ALL = ((1 << 3) - 1)
-} XdpAddFullFlags;
-
-G_END_DECLS
-
-#endif /* XDP_ENUMS_H */
diff --git a/document-portal/xdp-fuse.c b/document-portal/xdp-fuse.c
deleted file mode 100644
index 0d2f413f..00000000
--- a/document-portal/xdp-fuse.c
+++ /dev/null
@@ -1,2369 +0,0 @@
-#include "config.h"
-
-#define FUSE_USE_VERSION 26
-
-#include <glib-unix.h>
-
-#include <fuse_lowlevel.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <glib/gprintf.h>
-#include <gio/gio.h>
-#include <pthread.h>
-#include <sys/statfs.h>
-
-#include "flatpak-portal-error.h"
-#include "xdp-fuse.h"
-#include "xdp-util.h"
-#include "flatpak-utils.h"
-
-#define NON_DOC_DIR_PERMS 0500
-#define DOC_DIR_PERMS 0700
-
-/* TODO: What do we put here */
-#define ATTR_CACHE_TIME 60.0
-#define ENTRY_CACHE_TIME 60.0
-
-/* We pretend that the file is hardlinked. This causes most apps to do
- a truncating overwrite, which suits us better, as we do the atomic
- rename ourselves anyway. */
-#define DOC_FILE_NLINK 2
-
-typedef enum {
- XDP_INODE_ROOT,
- XDP_INODE_BY_APP,
- XDP_INODE_APP_DIR, /* app id */
- XDP_INODE_APP_DOC_DIR, /* app_id + doc id */
- XDP_INODE_DOC_DIR, /* doc id */
- XDP_INODE_DOC_FILE, /* doc id (NULL if tmp), name (== basename) */
-} XdpInodeType;
-
-typedef struct _XdpInode XdpInode;
-
-struct _XdpInode
-{
- gint ref_count; /* atomic */
-
- /* These are all immutable */
- fuse_ino_t ino;
- XdpInodeType type;
- XdpInode *parent;
- char *app_id;
- char *doc_id;
-
- /* For doc dirs */
- char *basename;
- char *dirname;
- dev_t dir_dev;
- ino_t dir_ino;
-
- /* mutable data */
-
- GList *children; /* lazily filled, protected by inodes lock */
- char *filename; /* variable (for non-dirs), null if deleted,
- protected by inodes lock *and* mutex */
- gboolean is_doc; /* True if this is the document file for this dir */
-
- /* Used when the file is open, protected by mutex */
- GMutex mutex; /* Always lock inodes lock (if needed) before mutex */
- GList *open_files;
- int dir_fd;
- int fd; /* RW fd for tempfiles, RO fd for doc files */
- char *backing_filename;
- char *trunc_filename;
- int trunc_fd;
- gboolean truncated;
-};
-
-typedef struct _XdpFile XdpFile;
-
-struct _XdpFile
-{
- XdpInode *inode;
- int open_mode;
-};
-
-#define ROOT_INODE 1
-#define BY_APP_INODE 2
-#define BY_APP_NAME "by-app"
-
-static GHashTable *dir_to_inode_nr;
-
-static GHashTable *inodes; /* The in memory XdpInode:s, protected by inodes lock */
-static XdpInode *root_inode;
-static XdpInode *by_app_inode;
-static fuse_ino_t next_inode_nr = 3;
-
-G_LOCK_DEFINE (inodes);
-
-static GThread *fuse_thread = NULL;
-static struct fuse_session *session = NULL;
-static struct fuse_chan *main_ch = NULL;
-static char *mount_path = NULL;
-static pthread_t fuse_pthread = 0;
-
-static int
-reopen_fd (int fd, int flags)
-{
- g_autofree char *path = g_strdup_printf ("/proc/self/fd/%d", fd);
-
- return open (path, flags | O_CLOEXEC);
-}
-
-/* Call with inodes lock held */
-static fuse_ino_t
-allocate_inode_unlocked (void)
-{
- fuse_ino_t next = next_inode_nr++;
-
- /* Bail out on overflow, to avoid reuse */
- if (next <= 0)
- g_assert_not_reached ();
-
- return next;
-}
-
-static fuse_ino_t
-get_dir_inode_nr_unlocked (const char *app_id, const char *doc_id)
-{
- gpointer res;
- fuse_ino_t allocated;
- g_autofree char *dir = NULL;
-
- if (app_id == NULL)
- {
- dir = g_strdup (doc_id);
- }
- else
- {
- if (doc_id == NULL)
- dir = g_strconcat (app_id, "/", NULL);
- else
- dir = g_build_filename (app_id, doc_id, NULL);
- }
-
- res = g_hash_table_lookup (dir_to_inode_nr, dir);
- if (res != NULL)
- return (fuse_ino_t) (gsize) res;
-
- allocated = allocate_inode_unlocked ();
- g_hash_table_insert (dir_to_inode_nr, g_strdup (dir), (gpointer) allocated);
- return allocated;
-}
-
-static fuse_ino_t
-get_dir_inode_nr (const char *app_id, const char *doc_id)
-{
- AUTOLOCK (inodes);
- return get_dir_inode_nr_unlocked (app_id, doc_id);
-}
-
-static void
-allocate_app_dir_inode_nr (char **app_ids)
-{
- int i;
-
- AUTOLOCK (inodes);
- for (i = 0; app_ids[i] != NULL; i++)
- get_dir_inode_nr_unlocked (app_ids[i], NULL);
-}
-
-static char **
-get_allocated_app_dirs (void)
-{
- GHashTableIter iter;
- gpointer key, value;
- GPtrArray *array = g_ptr_array_new ();
-
- AUTOLOCK (inodes);
- g_hash_table_iter_init (&iter, dir_to_inode_nr);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- const char *name = key;
-
- if (g_str_has_suffix (name, "/"))
- {
- char *app = strndup (name, strlen (name) - 1);
- g_ptr_array_add (array, app);
- }
- }
- g_ptr_array_add (array, NULL);
- return (char **) g_ptr_array_free (array, FALSE);
-}
-
-static void xdp_inode_unref_internal (XdpInode *inode,
- gboolean locked);
-static void xdp_inode_unref (XdpInode *inode);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (XdpInode, xdp_inode_unref)
-
-static void
-xdp_inode_destroy (XdpInode *inode, gboolean locked)
-{
- g_assert (inode->dir_fd == -1);
- g_assert (inode->fd == -1);
- g_assert (inode->trunc_fd == -1);
- g_assert (inode->trunc_filename == NULL);
- g_assert (inode->children == NULL);
- xdp_inode_unref_internal (inode->parent, locked);
- g_free (inode->backing_filename);
- g_free (inode->filename);
- g_free (inode->dirname);
- g_free (inode->app_id);
- g_free (inode->doc_id);
- g_free (inode);
-}
-
-static XdpInode *
-xdp_inode_ref (XdpInode *inode)
-{
- if (inode)
- g_atomic_int_inc (&inode->ref_count);
- return inode;
-}
-
-static void
-xdp_inode_unref_internal (XdpInode *inode, gboolean locked)
-{
- gint old_ref;
-
- if (inode == NULL)
- return;
-
- /* here we want to atomically do: if (ref_count>1) { ref_count--; return; } */
-retry_atomic_decrement1:
- old_ref = g_atomic_int_get (&inode->ref_count);
- if (old_ref > 1)
- {
- if (!g_atomic_int_compare_and_exchange ((int *) &inode->ref_count, old_ref, old_ref - 1))
- goto retry_atomic_decrement1;
- }
- else
- {
- if (old_ref <= 0)
- {
- g_warning ("Can't unref dead inode");
- return;
- }
- /* Protect against revival from xdp_inode_lookup() */
- if (!locked)
- G_LOCK (inodes);
- if (!g_atomic_int_compare_and_exchange ((int *) &inode->ref_count, old_ref, old_ref - 1))
- {
- if (!locked)
- G_UNLOCK (inodes);
- goto retry_atomic_decrement1;
- }
-
- g_hash_table_remove (inodes, (gpointer) inode->ino);
- if (inode->parent)
- inode->parent->children = g_list_remove (inode->parent->children, inode);
-
- if (!locked)
- G_UNLOCK (inodes);
-
- xdp_inode_destroy (inode, locked);
- }
-}
-
-static void
-xdp_inode_unref (XdpInode *inode)
-{
- return xdp_inode_unref_internal (inode, FALSE);
-}
-
-static XdpInode *
-xdp_inode_new_unlocked (fuse_ino_t ino,
- XdpInodeType type,
- XdpInode *parent,
- const char *filename,
- const char *app_id,
- const char *doc_id)
-{
- XdpInode *inode;
-
- inode = g_new0 (XdpInode, 1);
- inode->ino = ino;
- inode->type = type;
- inode->parent = xdp_inode_ref (parent);
- inode->filename = g_strdup (filename);
- inode->app_id = g_strdup (app_id);
- inode->doc_id = g_strdup (doc_id);
- inode->ref_count = 1;
- inode->dir_fd = -1;
- inode->fd = -1;
- inode->trunc_fd = -1;
-
- if (parent)
- parent->children = g_list_prepend (parent->children, inode);
- g_hash_table_insert (inodes, (gpointer) ino, inode);
-
- return inode;
-}
-
-static XdpInode *
-xdp_inode_new (fuse_ino_t ino,
- XdpInodeType type,
- XdpInode *parent,
- const char *filename,
- const char *app_id,
- const char *doc_id)
-{
- AUTOLOCK (inodes);
- return xdp_inode_new_unlocked (ino, type, parent, filename, app_id, doc_id);
-}
-
-static XdpInode *
-xdp_inode_lookup_unlocked (fuse_ino_t inode_nr)
-{
- XdpInode *inode;
-
- inode = g_hash_table_lookup (inodes, (gpointer) inode_nr);
- if (inode != NULL)
- return xdp_inode_ref (inode);
- return NULL;
-}
-
-static GList *
-xdp_inode_list_children (XdpInode *inode)
-{
- GList *list = NULL, *l;
-
- AUTOLOCK (inodes);
- for (l = inode->children; l != NULL; l = l->next)
- {
- XdpInode *child = l->data;
-
- list = g_list_prepend (list, xdp_inode_ref (child));
- }
-
- return g_list_reverse (list);
-}
-
-static XdpInode *
-xdp_inode_lookup_child_unlocked (XdpInode *inode, const char *filename)
-{
- GList *l;
-
- for (l = inode->children; l != NULL; l = l->next)
- {
- XdpInode *child = l->data;
- if (child->filename != NULL && strcmp (child->filename, filename) == 0)
- return xdp_inode_ref (child);
- }
-
- return NULL;
-}
-
-static XdpInode *
-xdp_inode_lookup_child (XdpInode *inode, const char *filename)
-{
- AUTOLOCK (inodes);
- return xdp_inode_lookup_child_unlocked (inode, filename);
-}
-
-static int
-xdp_inode_open_dir_fd (XdpInode *dir)
-{
- struct stat st_buf;
- glnx_autofd int fd = -1;
-
- g_assert (dir->dirname != NULL);
-
- fd = open (dir->dirname, O_CLOEXEC | O_PATH | O_DIRECTORY);
- if (fd == -1)
- return -1;
-
- if (fstat (fd, &st_buf) < 0)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (st_buf.st_ino != dir->dir_ino ||
- st_buf.st_dev != dir->dir_dev)
- {
- errno = ENOENT;
- return -1;
- }
-
- return glnx_steal_fd (&fd);
-}
-
-static void
-xdp_inode_unlink_backing_files (XdpInode *child_inode, int dir_fd)
-{
- if (dir_fd == -1)
- {
- g_debug ("Can't unlink child inode due to no dir_fd");
- return;
- }
-
- if (child_inode->is_doc)
- {
- g_debug ("unlinking doc file %s", child_inode->filename);
- unlinkat (dir_fd, child_inode->filename, 0);
- if (child_inode->trunc_filename != NULL)
- {
- g_debug ("unlinking doc trunc_file %s", child_inode->trunc_filename);
- unlinkat (dir_fd, child_inode->trunc_filename, 0);
- }
- }
- else
- {
- g_debug ("unlinking tmp_file %s", child_inode->backing_filename);
- unlinkat (dir_fd, child_inode->backing_filename, 0);
- }
-}
-
-static void
-xdp_inode_do_unlink (XdpInode *child_inode, int dir_fd, gboolean unlink_backing)
-{
- if (unlink_backing)
- xdp_inode_unlink_backing_files (child_inode, dir_fd);
-
- /* Zero out filename to mark it deleted */
- g_free (child_inode->filename);
- child_inode->filename = NULL;
-
- /* Drop keep-alive-until-unlink ref */
- if (!child_inode->is_doc)
- xdp_inode_unref (child_inode);
-}
-
-static XdpInode *
-xdp_inode_unlink_child (XdpInode *dir, const char *filename)
-{
- XdpInode *child_inode;
- glnx_autofd int dir_fd = -1;
-
- AUTOLOCK (inodes);
- child_inode = xdp_inode_lookup_child_unlocked (dir, filename);
- if (child_inode == NULL)
- return NULL;
-
- g_assert (child_inode->type == XDP_INODE_DOC_FILE);
- g_assert (child_inode->filename != NULL);
-
- /* Here we take *both* the inodes lock and the mutex.
- The inodes lock is to make this safe against concurrent lookups,
- but the mutex is to make it safe to access inode->filename inside
- a mutex-only lock */
- g_mutex_lock (&child_inode->mutex);
-
- dir_fd = xdp_inode_open_dir_fd (dir);
-
- xdp_inode_do_unlink (child_inode, dir_fd, TRUE);
-
- g_mutex_unlock (&child_inode->mutex);
-
- return child_inode;
-}
-
-/* Sets errno */
-static int
-xdp_inode_rename_child (XdpInode *dir,
- const char *src_filename,
- const char *dst_filename)
-{
- g_autoptr(XdpInode) src_inode = NULL;
- g_autoptr(XdpInode) dst_inode = NULL;
- glnx_autofd int dir_fd = -1;
- int res;
-
- AUTOLOCK (inodes);
- src_inode = xdp_inode_lookup_child_unlocked (dir, src_filename);
- if (src_inode == NULL)
- {
- errno = ENOENT;
- return -1;
- }
-
- g_assert (src_inode->type == XDP_INODE_DOC_FILE);
- g_assert (src_inode->filename != NULL);
-
- dst_inode = xdp_inode_lookup_child_unlocked (dir, dst_filename);
- if (dst_inode)
- {
- g_assert (dst_inode->type == XDP_INODE_DOC_FILE);
- g_assert (dst_inode->filename != NULL);
- }
-
- /* Here we take *both* the inodes lock and the mutex.
- The inodes lock is to make this safe against concurrent lookups,
- but the mutex is to make it safe to access inode->filename inside
- a mutex-only lock */
- g_mutex_lock (&src_inode->mutex);
- if (dst_inode)
- g_mutex_lock (&dst_inode->mutex);
-
- dir_fd = xdp_inode_open_dir_fd (dir);
- res = 0;
-
- if (src_inode->is_doc)
- {
- /* doc -> tmp */
-
- /* We don't want to allow renaming an exiting doc file, because
- doing so would make a tmpfile of the real doc-file which some
- host-side app may have open. You have to make a copy and
- remove instead. */
- errno = EACCES;
- res = -1;
- }
- else if (strcmp (dst_filename, dir->basename) != 0)
- {
- /* tmp -> tmp */
-
- if (dst_inode)
- xdp_inode_do_unlink (dst_inode, dir_fd, TRUE);
-
- g_free (src_inode->filename);
- src_inode->filename = g_strdup (dst_filename);
- }
- else
- {
- /* tmp -> doc */
-
- g_debug ("atomic renaming %s to %s", src_inode->backing_filename, dst_filename);
- res = renameat (dir_fd, src_inode->backing_filename,
- dir_fd, dst_filename);
- if (res == 0)
- {
- if (dst_inode != NULL)
- {
- /* Unlink, but don't remove backing files, which are now the new one */
- xdp_inode_do_unlink (dst_inode, dir_fd, FALSE);
-
- /* However, unlink trunc_file if its there */
- if (dst_inode->trunc_filename)
- unlinkat (dir_fd, dst_inode->trunc_filename, 0);
- }
-
- src_inode->is_doc = TRUE;
- g_free (src_inode->filename);
- src_inode->filename = g_strdup (dst_filename);
- g_free (src_inode->backing_filename);
- src_inode->backing_filename = g_strdup (dst_filename);
-
- /* Convert ->fd to read-only */
- if (src_inode->fd != -1)
- {
- int new_fd = reopen_fd (src_inode->fd, O_RDONLY);
- close (src_inode->fd);
- src_inode->fd = new_fd;
- }
-
- /* This neuters any outstanding write files, since we have no trunc_fd at this point.
- However, that is not really a problem, we would not support them well anyway as
- a newly opened trunc file would have to have a truncate operation initially for
- it to work anyway */
- }
- }
-
- g_mutex_unlock (&src_inode->mutex);
- if (dst_inode)
- g_mutex_unlock (&dst_inode->mutex);
-
- return res;
-}
-
-/* NULL if removed */
-static char *
-xdp_inode_get_filename (XdpInode *inode)
-{
- AUTOLOCK (inodes);
- return g_strdup (inode->filename);
-}
-
-static XdpInode *
-xdp_inode_ensure_document_file (XdpInode *dir)
-{
- XdpInode *inode;
-
- g_assert (dir->type == XDP_INODE_APP_DOC_DIR || dir->type == XDP_INODE_DOC_DIR);
-
- AUTOLOCK (inodes);
-
- inode = xdp_inode_lookup_child_unlocked (dir, dir->basename);
- if (inode == NULL)
- {
- inode = xdp_inode_new_unlocked (allocate_inode_unlocked (),
- XDP_INODE_DOC_FILE,
- dir,
- dir->basename,
- dir->app_id,
- dir->doc_id);
- inode->backing_filename = g_strdup (dir->basename);
- inode->is_doc = TRUE;
- }
-
- return inode;
-}
-
-static char *
-create_tmp_for_doc (XdpInode *dir, int dir_fd, int flags, mode_t mode, int *fd_out)
-{
- g_autofree char *template = g_strconcat (".xdp_", dir->basename, ".XXXXXX", NULL);
- int fd;
-
- fd = flatpak_mkstempat (dir_fd, template, flags | O_CLOEXEC, mode);
- if (fd == -1)
- return NULL;
-
- g_debug ("Created temp file %s", template);
- *fd_out = fd;
- return g_steal_pointer (&template);
-}
-
-/* sets errno */
-static XdpInode *
-xdp_inode_create_file (XdpInode *dir,
- const char *filename,
- mode_t mode,
- gboolean truncate,
- gboolean exclusive)
-{
- XdpInode *inode;
- g_autofree char *backing_filename = NULL;
- g_autofree char *trunc_filename = NULL;
- gboolean is_doc;
- glnx_autofd int dir_fd = -1;
- glnx_autofd int fd = -1;
- glnx_autofd int trunc_fd = -1;
-
- g_assert (dir->type == XDP_INODE_APP_DOC_DIR || dir->type == XDP_INODE_DOC_DIR);
-
- AUTOLOCK (inodes);
-
- inode = xdp_inode_lookup_child_unlocked (dir, filename);
- if (inode != NULL)
- {
- if (exclusive)
- {
- xdp_inode_unref (inode);
- errno = EEXIST;
- return NULL;
- }
-
- if (truncate)
- {
- /* TODO: Handle extra truncate for existing file */
- errno = ENOSYS;
- return NULL;
- }
-
- return inode;
- }
-
- dir_fd = xdp_inode_open_dir_fd (dir);
- if (dir_fd == -1)
- return NULL;
-
- is_doc = strcmp (dir->basename, filename) == 0;
-
- if (is_doc)
- {
- backing_filename = g_strdup (filename);
- int flags = O_CREAT | O_RDONLY | O_NOFOLLOW | O_CLOEXEC;
-
- if (exclusive)
- flags |= O_EXCL;
-
- g_debug ("Creating doc file %s", dir->basename);
- fd = openat (dir_fd, dir->basename, flags, mode & 0777);
- if (fd < 0)
- return NULL;
-
- trunc_filename = create_tmp_for_doc (dir, dir_fd, O_RDWR, mode & 0777, &trunc_fd);
- if (trunc_filename == NULL)
- return NULL;
- }
- else
- {
- backing_filename = create_tmp_for_doc (dir, dir_fd, O_RDWR, mode & 0777, &fd);
- if (backing_filename == NULL)
- return NULL;
- }
-
- inode = xdp_inode_new_unlocked (allocate_inode_unlocked (),
- XDP_INODE_DOC_FILE,
- dir,
- filename,
- dir->app_id,
- dir->doc_id);
- inode->backing_filename = g_steal_pointer (&backing_filename);
- inode->trunc_filename = g_steal_pointer (&trunc_filename);
- inode->is_doc = is_doc;
- inode->dir_fd = glnx_steal_fd (&dir_fd);
- inode->fd = glnx_steal_fd (&fd);
- inode->trunc_fd = glnx_steal_fd (&trunc_fd);
- if (inode->trunc_fd != -1 && (truncate || exclusive))
- {
- inode->truncated = TRUE;
- g_free (inode->backing_filename);
- inode->backing_filename = g_strdup (inode->trunc_filename);
- }
-
- /* We add an extra ref for tmp files to keep them alive until unlink */
- if (!is_doc)
- xdp_inode_ref (inode);
-
- return inode;
-}
-
-static XdpInode *
-xdp_inode_lookup (fuse_ino_t inode_nr)
-{
- AUTOLOCK (inodes);
- return xdp_inode_lookup_unlocked (inode_nr);
-}
-
-static XdpInode *
-xdp_inode_get_dir_unlocked (const char *app_id, const char *doc_id, FlatpakDbEntry *entry)
-{
- fuse_ino_t ino;
- XdpInode *inode;
- XdpInode *parent = NULL;
- XdpInodeType type;
- const char *filename;
-
- ino = get_dir_inode_nr_unlocked (app_id, doc_id);
-
- inode = xdp_inode_lookup_unlocked (ino);
- if (inode)
- return inode;
-
- if (app_id == NULL)
- {
- g_assert (doc_id != NULL);
- parent = xdp_inode_ref (root_inode);
- type = XDP_INODE_DOC_DIR;
- filename = doc_id;
- }
- else
- {
- if (doc_id == NULL)
- {
- parent = xdp_inode_ref (by_app_inode);
- filename = app_id;
- type = XDP_INODE_APP_DIR;
- }
- else
- {
- parent = xdp_inode_get_dir_unlocked (app_id, NULL, NULL);
- filename = doc_id;
- type = XDP_INODE_APP_DOC_DIR;
- }
- }
-
- inode = xdp_inode_new_unlocked (ino, type, parent, filename, app_id, doc_id);
- xdp_inode_unref_internal (parent, TRUE);
-
- if (entry)
- {
- inode->basename = xdp_entry_dup_basename (entry);
- inode->dirname = xdp_entry_dup_dirname (entry);
- inode->dir_ino = xdp_entry_get_inode (entry);
- inode->dir_dev = xdp_entry_get_device (entry);
- }
-
- return inode;
-}
-
-static XdpInode *
-xdp_inode_get_dir (const char *app_id, const char *doc_id, FlatpakDbEntry *entry)
-{
- AUTOLOCK (inodes);
- return xdp_inode_get_dir_unlocked (app_id, doc_id, entry);
-}
-
-/********************************************************************** \
-* FUSE Implementation
-\***********************************************************************/
-
-static int
-get_user_perms (const struct stat *stbuf)
-{
- /* Strip out exec and setuid bits */
- return stbuf->st_mode & 0666;
-}
-
-static gboolean
-app_can_write_doc (FlatpakDbEntry *entry, const char *app_id)
-{
- if (app_id == NULL)
- return TRUE;
-
- if (xdp_entry_has_permissions (entry, app_id, XDP_PERMISSION_FLAGS_WRITE))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-app_can_see_doc (FlatpakDbEntry *entry, const char *app_id)
-{
- if (app_id == NULL)
- return TRUE;
-
- if (xdp_entry_has_permissions (entry, app_id, XDP_PERMISSION_FLAGS_READ))
- return TRUE;
-
- return FALSE;
-}
-
-/* Call with mutex held! */
-static int
-xdp_inode_locked_get_fd (XdpInode *inode)
-{
- if (inode->truncated)
- return inode->trunc_fd;
-
- return inode->fd;
-}
-
-/* Call with mutex held! */
-static int
-xdp_inode_locked_get_write_fd (XdpInode *inode)
-{
- if (inode->is_doc)
- {
- if (!inode->truncated)
- {
- errno = ENOSYS;
- return -1;
- }
- return inode->trunc_fd;
- }
-
- return inode->fd;
-}
-
-static int
-xdp_inode_stat (XdpInode *inode,
- struct stat *stbuf)
-{
- stbuf->st_ino = inode->ino;
- stbuf->st_uid = getuid ();
- stbuf->st_gid = getgid ();
-
- switch (inode->type)
- {
- case XDP_INODE_ROOT:
- case XDP_INODE_BY_APP:
- case XDP_INODE_APP_DIR:
- stbuf->st_mode = S_IFDIR | NON_DOC_DIR_PERMS;
- stbuf->st_nlink = 2;
- break;
-
- case XDP_INODE_DOC_DIR:
- case XDP_INODE_APP_DOC_DIR:
- stbuf->st_mode = S_IFDIR | DOC_DIR_PERMS;
- stbuf->st_nlink = 2;
- break;
-
- case XDP_INODE_DOC_FILE:
- {
- g_autoptr(FlatpakDbEntry) entry = NULL;
- struct stat tmp_stbuf;
- gboolean can_see, can_write;
- int fd, res, errsv;
-
- entry = xdp_lookup_doc (inode->doc_id);
- if (entry == NULL)
- {
- errno = ENOENT;
- return -1;
- }
-
- can_see = app_can_see_doc (entry, inode->app_id);
- can_write = app_can_write_doc (entry, inode->app_id);
-
- if (!can_see)
- {
- errno = ENOENT;
- return -1;
- }
-
- g_mutex_lock (&inode->mutex);
-
- fd = xdp_inode_locked_get_fd (inode);
- if (fd != -1)
- {
- res = fstat (fd, &tmp_stbuf);
- }
- else
- {
- glnx_autofd int dir_fd = xdp_inode_open_dir_fd (inode->parent);
-
- if (dir_fd == -1)
- res = -1;
- else
- res = fstatat (dir_fd, inode->backing_filename,
- &tmp_stbuf, AT_SYMLINK_NOFOLLOW);
- }
- errsv = errno;
-
- g_mutex_unlock (&inode->mutex);
-
- if (res != 0)
- {
- errno = errsv;
- return -1;
- }
-
- stbuf->st_mode = S_IFREG | get_user_perms (&tmp_stbuf);
- if (!can_write)
- stbuf->st_mode &= ~(0222);
- stbuf->st_size = tmp_stbuf.st_size;
- stbuf->st_uid = tmp_stbuf.st_uid;
- stbuf->st_gid = tmp_stbuf.st_gid;
- stbuf->st_blksize = tmp_stbuf.st_blksize;
- stbuf->st_blocks = tmp_stbuf.st_blocks;
- stbuf->st_atim = tmp_stbuf.st_atim;
- stbuf->st_mtim = tmp_stbuf.st_mtim;
- stbuf->st_ctim = tmp_stbuf.st_ctim;
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- return 0;
-}
-
-static void
-xdp_fuse_lookup (fuse_req_t req,
- fuse_ino_t parent,
- const char *name)
-{
- g_autoptr(XdpInode) parent_inode = NULL;
- struct fuse_entry_param e = {0};
- g_autoptr(XdpInode) child_inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- g_debug ("xdp_fuse_lookup %lx/%s -> ", parent, name);
-
- parent_inode = xdp_inode_lookup (parent);
- if (parent_inode == NULL)
- {
- g_debug ("xdp_fuse_lookup <- error parent ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- /* Default */
- e.attr_timeout = ATTR_CACHE_TIME;
- e.entry_timeout = ENTRY_CACHE_TIME;
-
- switch (parent_inode->type)
- {
- case XDP_INODE_ROOT:
- if (strcmp (name, BY_APP_NAME) == 0)
- {
- child_inode = xdp_inode_ref (by_app_inode);
- }
- else
- {
- entry = xdp_lookup_doc (name);
- if (entry != NULL)
- child_inode = xdp_inode_get_dir (NULL, name, entry);
- }
- break;
-
- case XDP_INODE_BY_APP:
- /* This lazily creates the app dir */
- if (flatpak_is_valid_name (name, NULL))
- child_inode = xdp_inode_get_dir (name, NULL, NULL);
- break;
-
- case XDP_INODE_APP_DIR:
- entry = xdp_lookup_doc (name);
- if (entry != NULL &&
- app_can_see_doc (entry, parent_inode->app_id))
- child_inode = xdp_inode_get_dir (parent_inode->app_id, name, entry);
- break;
-
- case XDP_INODE_APP_DOC_DIR:
- case XDP_INODE_DOC_DIR:
- {
- g_autoptr(XdpInode) doc_inode = NULL;
- entry = xdp_lookup_doc (parent_inode->doc_id);
- if (entry == NULL)
- {
- g_debug ("xdp_fuse_lookup <- error no parent entry ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- /* Ensure it is alive at least during lookup_child () */
- doc_inode = xdp_inode_ensure_document_file (parent_inode);
-
- child_inode = xdp_inode_lookup_child (parent_inode, name);
-
- /* We verify in the stat below if the backing file exists */
-
- /* Files can be changed from outside the fuse fs, so don't cache any data */
- e.attr_timeout = 0;
- e.entry_timeout = 0;
- }
- break;
-
- case XDP_INODE_DOC_FILE:
- fuse_reply_err (req, ENOTDIR);
- return;
-
- default:
- break;
- }
-
- if (child_inode == NULL)
- {
- g_debug ("xdp_fuse_lookup <- error child ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (xdp_inode_stat (child_inode, &e.attr) != 0)
- {
- fuse_reply_err (req, errno);
- return;
- }
-
- e.ino = child_inode->ino;
-
- g_debug ("xdp_fuse_lookup <- inode %lx", (long) e.ino);
- xdp_inode_ref (child_inode); /* Ref given to the kernel, returned in xdp_fuse_forget() */
- fuse_reply_entry (req, &e);
-}
-
-static void
-xdp_fuse_forget (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
-{
- g_autoptr(XdpInode) inode = NULL;
- g_debug ("xdp_fuse_forget %lx %ld -> ", ino, nlookup);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_warning ("xdp_fuse_forget, unknown inode");
- }
- else
- {
- while (nlookup > 0)
- {
- xdp_inode_unref (inode);
- nlookup--;
- }
- }
-
- fuse_reply_none (req);
-}
-
-struct dirbuf
-{
- char *p;
- size_t size;
-};
-
-static void
-dirbuf_add (fuse_req_t req,
- struct dirbuf *b,
- const char *name,
- fuse_ino_t ino,
- mode_t mode)
-{
- struct stat stbuf;
-
- size_t oldsize = b->size;
-
- b->size += fuse_add_direntry (req, NULL, 0, name, NULL, 0);
- b->p = (char *) g_realloc (b->p, b->size);
- memset (&stbuf, 0, sizeof (stbuf));
- stbuf.st_ino = ino;
- stbuf.st_mode = mode;
- fuse_add_direntry (req, b->p + oldsize,
- b->size - oldsize,
- name, &stbuf,
- b->size);
-}
-
-static void
-dirbuf_add_docs (fuse_req_t req,
- struct dirbuf *b,
- const char *app_id)
-{
- g_auto(GStrv) docs = NULL;
- fuse_ino_t ino;
- int i;
-
- docs = xdp_list_docs ();
- for (i = 0; docs[i] != NULL; i++)
- {
- if (app_id)
- {
- g_autoptr(FlatpakDbEntry) entry = xdp_lookup_doc (docs[i]);
- if (entry == NULL ||
- !app_can_see_doc (entry, app_id))
- continue;
- }
- ino = get_dir_inode_nr (app_id, docs[i]);
- dirbuf_add (req, b, docs[i], ino, S_IFDIR);
- }
-}
-
-static int
-reply_buf_limited (fuse_req_t req,
- const char *buf,
- size_t bufsize,
- off_t off,
- size_t maxsize)
-{
- if (off < bufsize)
- return fuse_reply_buf (req, buf + off,
- MIN (bufsize - off, maxsize));
- else
- return fuse_reply_buf (req, NULL, 0);
-}
-
-static void
-xdp_fuse_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
- off_t off, struct fuse_file_info *fi)
-{
- struct dirbuf *b = (struct dirbuf *) (gsize) (fi->fh);
-
- reply_buf_limited (req, b->p, b->size, off, size);
-}
-
-static void
-xdp_fuse_opendir (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
- struct dirbuf b = {0};
-
- g_debug ("xdp_fuse_opendir %lx", ino);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_opendir <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- switch (inode->type)
- {
- case XDP_INODE_ROOT:
- dirbuf_add (req, &b, ".", ROOT_INODE, S_IFDIR);
- dirbuf_add (req, &b, "..", ROOT_INODE, S_IFDIR);
- dirbuf_add (req, &b, BY_APP_NAME, BY_APP_INODE, S_IFDIR);
- dirbuf_add_docs (req, &b, NULL);
- break;
-
- case XDP_INODE_BY_APP:
- {
- g_auto(GStrv) db_app_ids = NULL;
- g_auto(GStrv) app_ids = NULL;
- int i;
-
- dirbuf_add (req, &b, ".", BY_APP_INODE, S_IFDIR);
- dirbuf_add (req, &b, "..", ROOT_INODE, S_IFDIR);
-
- /* Ensure that all apps from db are allocated */
- db_app_ids = xdp_list_apps ();
- allocate_app_dir_inode_nr (db_app_ids);
-
- /* But return all allocated dirs. We might have app dirs
- that have no permissions, and are thus not in the db */
- app_ids = get_allocated_app_dirs ();
- for (i = 0; app_ids[i] != NULL; i++)
- dirbuf_add (req, &b, app_ids[i],
- get_dir_inode_nr (app_ids[i], NULL), S_IFDIR);
- }
- break;
-
- case XDP_INODE_APP_DIR:
- dirbuf_add (req, &b, ".", inode->ino, S_IFDIR);
- dirbuf_add (req, &b, "..", BY_APP_INODE, S_IFDIR);
- dirbuf_add_docs (req, &b, inode->app_id);
- break;
-
- case XDP_INODE_DOC_FILE:
- fuse_reply_err (req, ENOTDIR);
- break;
-
- case XDP_INODE_APP_DOC_DIR:
- case XDP_INODE_DOC_DIR:
- {
- GList *children, *l;
- g_autoptr(XdpInode) doc_inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- entry = xdp_lookup_doc (inode->doc_id);
- if (entry == NULL)
- {
- fuse_reply_err (req, ENOENT);
- break;
- }
-
- dirbuf_add (req, &b, ".", inode->ino, S_IFDIR);
- dirbuf_add (req, &b, "..", inode->parent->ino, S_IFDIR);
-
- /* Ensure it is alive at least during list_children () */
- doc_inode = xdp_inode_ensure_document_file (inode);
-
- children = xdp_inode_list_children (inode);
-
- for (l = children; l != NULL; l = l->next)
- {
- struct stat stbuf;
- XdpInode *child = l->data;
- g_autofree char *filename = xdp_inode_get_filename (child);
- if (filename != NULL && xdp_inode_stat (child, &stbuf) == 0)
- dirbuf_add (req, &b, filename, child->ino, stbuf.st_mode);
- xdp_inode_unref (child);
- }
- g_list_free (children);
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- if (b.p != NULL)
- {
- fi->fh = (gsize) g_memdup (&b, sizeof (b));
- if (fuse_reply_open (req, fi) == -ENOENT)
- {
- g_free (b.p);
- g_free ((gpointer) (gsize) (fi->fh));
- }
- }
-}
-
-static void
-xdp_fuse_releasedir (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_file_info *fi)
-{
- struct dirbuf *b = (struct dirbuf *) (gsize) (fi->fh);
-
- g_free (b->p);
- g_free (b);
- fuse_reply_err (req, 0);
-}
-
-
-
-static void
-xdp_fuse_getattr (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
- struct stat stbuf = { 0 };
-
- g_debug ("xdp_fuse_getattr %lx (fi=%p)", ino, fi);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_getattr <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (xdp_inode_stat (inode, &stbuf) != 0)
- {
- fuse_reply_err (req, errno);
- return;
- }
-
- fuse_reply_attr (req, &stbuf, ATTR_CACHE_TIME);
-}
-
-static void
-xdp_fuse_fsyncdir (fuse_req_t req,
- fuse_ino_t ino,
- int datasync,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
-
- g_debug ("xdp_fuse_fsyncdir %lx %p", ino, fi);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_fsyncdir <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (inode->type == XDP_INODE_APP_DOC_DIR ||
- inode->type == XDP_INODE_DOC_DIR)
- {
- g_autoptr(FlatpakDbEntry) entry = xdp_lookup_doc (inode->doc_id);
- if (entry != NULL)
- {
- g_autofree char *dirname = xdp_entry_dup_dirname (entry);
- int fd = open (dirname, O_DIRECTORY | O_RDONLY);
- if (fd >= 0)
- {
- if (datasync)
- fdatasync (fd);
- else
- fsync (fd);
- close (fd);
- }
- }
- }
-
- fuse_reply_err (req, 0);
-}
-
-static XdpFile *
-xdp_file_new (XdpInode *inode,
- int open_mode)
-{
- XdpFile *file = g_new (XdpFile, 1);
-
- file->inode = xdp_inode_ref (inode);
- file->open_mode = open_mode;
-
- return file;
-}
-
-/* Call with mutex held */
-static void
-xdp_inode_locked_close_unneeded_fds (XdpInode *inode)
-{
- gboolean has_open_for_write = FALSE;
- GList *l;
-
- for (l = inode->open_files; l != NULL; l = l->next)
- {
- XdpFile *file = l->data;
-
- if (file->open_mode != O_RDONLY)
- {
- has_open_for_write = TRUE;
- break;
- }
- }
-
- if (!has_open_for_write)
- {
- if (inode->truncated)
- {
- if (inode->open_files != NULL && inode->fd != -1)
- {
- /* We're not going to close the ->fd, so we repoint it to the trunc_fd, but reopened O_RDONLY */
- close (inode->fd);
- inode->fd = reopen_fd (inode->trunc_fd, O_RDONLY);
- }
-
- if (inode->filename != NULL)
- {
- /* not removed, replace original */
- fsync (inode->trunc_fd);
- g_free (inode->backing_filename);
- inode->backing_filename = g_strdup (inode->filename);
- g_debug ("moving %s to %s", inode->trunc_filename, inode->backing_filename);
- if (renameat (inode->dir_fd, inode->trunc_filename,
- inode->dir_fd, inode->backing_filename) != 0)
- g_warning ("Unable to replace truncated document: %s", g_strerror (errno));
- }
-
- inode->truncated = FALSE;
- }
- else if (inode->trunc_filename != NULL)
- {
- unlinkat (inode->dir_fd, inode->trunc_filename, 0);
- g_debug ("unlinked truc_filename %s", inode->trunc_filename);
- }
-
- if (inode->trunc_fd != -1)
- {
- close (inode->trunc_fd);
- inode->trunc_fd = -1;
- g_free (inode->trunc_filename);
- inode->trunc_filename = NULL;
- }
- }
-
- if (inode->open_files == NULL)
- {
- if (inode->fd != -1)
- {
- close (inode->fd);
- inode->fd = -1;
- }
-
- if (inode->dir_fd != -1)
- {
- close (inode->dir_fd);
- inode->dir_fd = -1;
- }
- }
-}
-
-static void
-xdp_file_free (XdpFile *file)
-{
- XdpInode *inode = file->inode;
-
- g_mutex_lock (&inode->mutex);
- inode->open_files = g_list_remove (inode->open_files, file);
-
- xdp_inode_locked_close_unneeded_fds (inode);
-
- g_mutex_unlock (&inode->mutex);
- xdp_inode_unref (inode);
- g_free (file);
-}
-
-/* sets errno */
-static int
-xdp_inode_locked_ensure_fd_open (XdpInode *inode,
- FlatpakDbEntry *entry,
- gboolean for_write)
-{
- /* Ensure all fds are open */
- if (inode->dir_fd == -1)
- {
- inode->dir_fd = xdp_inode_open_dir_fd (inode->parent);
- if (inode->dir_fd == -1)
- return -1;
- }
-
- if (for_write)
- {
- if (faccessat (inode->dir_fd, inode->backing_filename, W_OK, 0) != 0)
- return -1;
- }
-
- if (inode->fd == -1)
- {
- int mode = O_NOFOLLOW | O_CLOEXEC;
-
- if (inode->is_doc)
- mode |= O_RDONLY;
- else
- mode |= O_RDWR;
-
- inode->fd = openat (inode->dir_fd, inode->backing_filename, mode);
- if (inode->fd < 0)
- return -1;
- }
-
- if (inode->is_doc && for_write && inode->trunc_fd == -1)
- {
- struct stat st_buf;
- mode_t mode = 0600;
-
- if (fstat (inode->fd, &st_buf) == 0)
- mode = get_user_perms (&st_buf);
-
- g_assert (inode->trunc_filename == NULL);
- inode->trunc_filename = create_tmp_for_doc (inode->parent, inode->dir_fd, O_RDWR, mode,
- &inode->trunc_fd);
- if (inode->trunc_filename == NULL)
- return -1;
- }
-
- return 0;
-}
-
-static void
-xdp_fuse_open (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
- gboolean can_write;
- int open_mode;
- XdpFile *file = NULL;
- int errsv;
-
- g_debug ("xdp_fuse_open %lx flags %o", ino, fi->flags);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_open <- no inode error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (inode->type != XDP_INODE_DOC_FILE)
- {
- g_debug ("xdp_fuse_open <- error EISDIR");
- fuse_reply_err (req, EISDIR);
- return;
- }
-
- entry = xdp_lookup_doc (inode->doc_id);
- if (entry == NULL ||
- !app_can_see_doc (entry, inode->app_id))
- {
- g_debug ("xdp_fuse_open <- no entry error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- can_write = app_can_write_doc (entry, inode->app_id);
-
- open_mode = fi->flags & 3;
-
- if (open_mode != O_RDONLY && !can_write)
- {
- g_debug ("xdp_fuse_open <- no write EACCES");
- fuse_reply_err (req, EACCES);
- return;
- }
-
- g_mutex_lock (&inode->mutex);
-
- if (xdp_inode_locked_ensure_fd_open (inode, entry,
- open_mode != O_RDONLY) == 0)
- {
- file = xdp_file_new (inode, open_mode);
- inode->open_files = g_list_prepend (inode->open_files, file);
- errsv = 0;
- }
- else
- {
- errsv = errno;
- xdp_inode_locked_close_unneeded_fds (inode);
- }
-
- g_mutex_unlock (&inode->mutex);
-
- if (file != NULL)
- {
- fi->fh = (gsize) file;
- if (fuse_reply_open (req, fi))
- xdp_file_free (file);
- }
- else
- {
- fuse_reply_err (req, errsv);
- }
-}
-
-
-static void
-xdp_fuse_create (fuse_req_t req,
- fuse_ino_t parent,
- const char *filename,
- mode_t mode,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) parent_inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
- struct fuse_entry_param e = {0};
- gboolean can_see, can_write;
- int open_mode;
- XdpFile *file = NULL;
- XdpInode *inode;
- int errsv;
-
- g_debug ("xdp_fuse_create %lx/%s, flags %o", parent, filename, fi->flags);
-
- parent_inode = xdp_inode_lookup (parent);
- if (parent_inode == NULL)
- {
- g_debug ("xdp_fuse_create <- error parent ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (parent_inode->type == XDP_INODE_DOC_FILE)
- {
- g_debug ("xdp_fuse_create <- error parent ENOTDIR");
- fuse_reply_err (req, ENOTDIR);
- return;
- }
-
- if (parent_inode->type != XDP_INODE_APP_DOC_DIR &&
- parent_inode->type != XDP_INODE_DOC_DIR)
- {
- fuse_reply_err (req, EACCES);
- return;
- }
-
- entry = xdp_lookup_doc (parent_inode->doc_id);
- if (entry == NULL)
- {
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- can_see = app_can_see_doc (entry, parent_inode->app_id);
- if (!can_see)
- {
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- can_write = app_can_write_doc (entry, parent_inode->app_id);
- if (!can_write)
- {
- fuse_reply_err (req, EACCES);
- return;
- }
-
- inode = xdp_inode_create_file (parent_inode, filename,
- mode,
- (fi->flags & O_TRUNC) != 0,
- (fi->flags & O_EXCL) != 0);
- if (inode == NULL)
- {
- fuse_reply_err (req, errno);
- return;
- }
-
- g_mutex_lock (&inode->mutex);
-
- open_mode = fi->flags & 3;
-
- if (xdp_inode_locked_ensure_fd_open (inode, entry,
- open_mode != O_RDONLY) == 0)
- {
- file = xdp_file_new (inode, open_mode);
- inode->open_files = g_list_prepend (inode->open_files, file);
- errsv = 0;
- }
- else
- {
- errsv = errno;
- xdp_inode_locked_close_unneeded_fds (inode);
- }
-
- g_mutex_unlock (&inode->mutex);
-
- if (file != NULL)
- {
- if (xdp_inode_stat (inode, &e.attr) != 0)
- {
- xdp_file_free (file);
- fuse_reply_err (req, errno);
- return;
- }
-
- e.ino = inode->ino;
- if (inode->is_doc)
- {
- e.attr_timeout = 0;
- e.entry_timeout = 0;
- }
- else
- {
- e.attr_timeout = ATTR_CACHE_TIME;
- e.entry_timeout = ENTRY_CACHE_TIME;
- }
-
- xdp_inode_ref (inode); /* Ref given to the kernel, returned in xdp_fuse_forget() */
-
- fi->fh = (gsize) file;
- if (fuse_reply_create (req, &e, fi))
- {
- xdp_file_free (file);
- xdp_inode_unref (inode);
- }
- }
- else
- {
- fuse_reply_err (req, errsv);
- }
-}
-
-static void
-xdp_fuse_read (fuse_req_t req,
- fuse_ino_t ino,
- size_t size,
- off_t off,
- struct fuse_file_info *fi)
-{
- XdpFile *file = (gpointer) (gsize) fi->fh;
- XdpInode *inode = file->inode;
- struct fuse_bufvec bufv = FUSE_BUFVEC_INIT (size);
- int fd;
-
- g_debug ("xdp_fuse_real %lx %ld %ld", ino, (long) size, (long) off);
-
- g_mutex_lock (&inode->mutex);
-
- fd = xdp_inode_locked_get_fd (inode);
- if (fd == -1)
- {
- static char c = 'x';
- bufv.buf[0].flags = 0;
- bufv.buf[0].mem = &c;
- bufv.buf[0].size = 0;
-
- fuse_reply_data (req, &bufv, FUSE_BUF_NO_SPLICE);
- }
- else
- {
- bufv.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
- bufv.buf[0].fd = fd;
- bufv.buf[0].pos = off;
-
- fuse_reply_data (req, &bufv, FUSE_BUF_SPLICE_MOVE);
- }
-
- g_mutex_unlock (&inode->mutex);
-}
-
-static void
-xdp_fuse_release (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_file_info *fi)
-{
- XdpFile *file = (gpointer) (gsize) fi->fh;
-
- g_debug ("xdp_fuse_release %lx (fi=%p)", ino, fi);
-
- xdp_file_free (file);
- fuse_reply_err (req, 0);
-}
-
-static int
-truncateat (int dir_fd, const char *filename, int size)
-{
- int fd;
- int errsv, res;
-
- fd = openat (dir_fd, filename, O_RDWR);
- if (fd == -1)
- return -1;
-
- res = ftruncate (fd, size);
- errsv = errno;
-
- close (fd);
-
- errno = errsv;
- return res;
-}
-
-static void
-xdp_fuse_setattr (fuse_req_t req,
- fuse_ino_t ino,
- struct stat *attr,
- int to_set,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
- double attr_cache_time = ATTR_CACHE_TIME;
- struct stat newattr = {0};
- gboolean can_write;
- int res = 0;
-
- g_debug ("xdp_fuse_setattr %lx %x %p", ino, to_set, fi);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_setattr <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (inode->type != XDP_INODE_DOC_FILE)
- {
- g_debug ("xdp_fuse_setattr <- not file ENOSYS");
- fuse_reply_err (req, ENOSYS);
- return;
- }
-
- entry = xdp_lookup_doc (inode->doc_id);
- if (entry == NULL ||
- !app_can_see_doc (entry, inode->app_id))
- {
- g_debug ("xdp_fuse_setattr <- no entry error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- can_write = app_can_write_doc (entry, inode->app_id);
-
- if (to_set == FUSE_SET_ATTR_SIZE)
- {
- g_mutex_lock (&inode->mutex);
-
- if (!can_write)
- {
- res = EACCES;
- }
- else if (inode->is_doc)
- {
- /* Only allow ftruncate with the file open for write. We could
- * allow a truncate, but it would have to be implemented as
- * an atomic-replace-with-empty-file to not affect other apps
- * having the file open.
- * Also, only support truncate-to-zero on first truncation, to
- * avoid having to copy lots of data from the old file to the
- * trunc_fd.
- */
- if (inode->trunc_fd == -1)
- {
- res = EACCES;
- }
- else if (!inode->truncated && attr->st_size != 0)
- {
- res = ENOSYS;
- }
- else
- {
- if (ftruncate (inode->trunc_fd, attr->st_size) != 0)
- {
- res = errno;
- }
- else if (!inode->truncated)
- {
- inode->truncated = TRUE;
- g_free (inode->backing_filename);
- inode->backing_filename = g_strdup (inode->trunc_filename);
- }
- }
- }
- else
- {
- if (inode->fd)
- {
- if (ftruncate (inode->fd, attr->st_size) != 0)
- res = errno;
- }
- else
- {
- glnx_autofd int dir_fd = xdp_inode_open_dir_fd (inode->parent);
- if (dir_fd == -1 ||
- truncateat (dir_fd, inode->backing_filename, attr->st_size) != 0)
- res = errno;
- }
- }
- g_mutex_unlock (&inode->mutex);
- }
- else if (to_set == FUSE_SET_ATTR_MODE)
- {
- if (!can_write)
- {
- res = EACCES;
- }
- else
- {
- int fd = xdp_inode_locked_get_write_fd (inode);
- if (fd == -1 ||
- fchmod (fd, get_user_perms (attr)) != 0)
- res = errno;
- }
- }
- else
- {
- res = ENOSYS;
- }
-
- if (res != 0)
- {
- fuse_reply_err (req, res);
- }
- else
- {
- if (xdp_inode_stat (inode, &newattr) != 0)
- fuse_reply_err (req, errno);
- else
- fuse_reply_attr (req, &newattr, attr_cache_time);
- }
-}
-
-static void
-xdp_fuse_write (fuse_req_t req,
- fuse_ino_t ino,
- const char *buf,
- size_t size,
- off_t off,
- struct fuse_file_info *fi)
-{
- XdpFile *file = (gpointer) (gsize) fi->fh;
- XdpInode *inode = file->inode;
- int fd;
- int res;
-
- g_debug ("xdp_fuse_write %lx %ld %ld", ino, (long) size, (long) off);
-
- g_mutex_lock (&inode->mutex);
-
- fd = xdp_inode_locked_get_write_fd (inode);
- if (fd < 0)
- {
- fuse_reply_err (req, errno);
- }
- else
- {
- res = pwrite (fd, buf, size, off);
- if (res < 0)
- fuse_reply_err (req, errno);
- else
- fuse_reply_write (req, res);
- }
-
- g_mutex_unlock (&inode->mutex);
-}
-
-static void
-xdp_fuse_write_buf (fuse_req_t req,
- fuse_ino_t ino,
- struct fuse_bufvec *bufv,
- off_t off,
- struct fuse_file_info *fi)
-{
- XdpFile *file = (gpointer) (gsize) fi->fh;
- struct fuse_bufvec dst = FUSE_BUFVEC_INIT (fuse_buf_size (bufv));
- XdpInode *inode = file->inode;
- int fd;
- int res;
-
- g_debug ("xdp_fuse_write_buf %lx %ld", ino, (long) off);
-
- g_mutex_lock (&inode->mutex);
-
- fd = xdp_inode_locked_get_write_fd (inode);
- if (fd == -1)
- {
- g_debug ("xdp_fuse_write_buf <- error %s", strerror (errno));
- fuse_reply_err (req, errno);
- }
- else
- {
- dst.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
- dst.buf[0].fd = fd;
- dst.buf[0].pos = off;
-
- res = fuse_buf_copy (&dst, bufv, FUSE_BUF_SPLICE_NONBLOCK);
- if (res < 0)
- fuse_reply_err (req, -res);
- else
- fuse_reply_write (req, res);
- }
-
- g_mutex_unlock (&inode->mutex);
-}
-
-static void
-xdp_fuse_fsync (fuse_req_t req,
- fuse_ino_t ino,
- int datasync,
- struct fuse_file_info *fi)
-{
- g_autoptr(XdpInode) inode = NULL;
- int fd;
- int res = 0;
-
- g_debug ("xdp_fuse_fsync %lx", ino);
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_setattr <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (inode->type == XDP_INODE_DOC_FILE)
- {
- g_mutex_lock (&inode->mutex);
-
- fd = xdp_inode_locked_get_write_fd (inode);
- if (fd != -1 && fsync (fd) != 0)
- res = errno;
-
- g_mutex_unlock (&inode->mutex);
- }
-
- fuse_reply_err (req, res);
-}
-
-static void
-xdp_fuse_unlink (fuse_req_t req,
- fuse_ino_t parent,
- const char *filename)
-{
- g_autoptr(XdpInode) parent_inode = NULL;
- g_autoptr(XdpInode) child_inode = NULL;
-
- g_debug ("xdp_fuse_unlink %lx/%s", parent, filename);
-
- parent_inode = xdp_inode_lookup (parent);
- if (parent_inode == NULL)
- {
- g_debug ("xdp_fuse_lookup <- error parent ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (parent_inode->type == XDP_INODE_DOC_FILE)
- {
- fuse_reply_err (req, ENOTDIR);
- return;
- }
-
- if (parent_inode->type != XDP_INODE_APP_DOC_DIR &&
- parent_inode->type != XDP_INODE_DOC_DIR)
- {
- fuse_reply_err (req, EACCES);
- return;
- }
-
- child_inode = xdp_inode_unlink_child (parent_inode, filename);
- if (child_inode == NULL)
- {
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- fuse_reply_err (req, 0);
-}
-
-static void
-xdp_fuse_rename (fuse_req_t req,
- fuse_ino_t parent,
- const char *name,
- fuse_ino_t newparent,
- const char *newname)
-{
- g_autoptr(XdpInode) parent_inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
- gboolean can_see, can_write;
-
- g_debug ("xdp_fuse_rename %lx/%s -> %lx/%s", parent, name, newparent, newname);
-
- parent_inode = xdp_inode_lookup (parent);
- if (parent_inode == NULL)
- {
- g_debug ("xdp_fuse_rename <- error parent ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (parent_inode->type == XDP_INODE_DOC_FILE)
- {
- fuse_reply_err (req, ENOTDIR);
- return;
- }
-
- if (parent_inode->type != XDP_INODE_APP_DOC_DIR &&
- parent_inode->type != XDP_INODE_DOC_DIR)
- {
- fuse_reply_err (req, EACCES);
- return;
- }
-
- if (newparent != parent)
- {
- g_debug ("xdp_fuse_rename <- error different parents EACCES");
- fuse_reply_err (req, EACCES);
- return;
- }
-
- if (strcmp (name, newname) == 0)
- {
- fuse_reply_err (req, 0);
- return;
- }
-
- entry = xdp_lookup_doc (parent_inode->doc_id);
- if (entry == NULL)
- {
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- can_see = app_can_see_doc (entry, parent_inode->app_id);
- can_write = app_can_write_doc (entry, parent_inode->app_id);
-
- if (!can_see)
- {
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (!can_write)
- {
- fuse_reply_err (req, EACCES);
- return;
- }
-
- if (xdp_inode_rename_child (parent_inode, name, newname) != 0)
- fuse_reply_err (req, errno);
- else
- fuse_reply_err (req, 0);
-}
-
-static void
-xdp_fuse_access (fuse_req_t req, fuse_ino_t ino, int mask)
-{
- g_autoptr(XdpInode) inode = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- g_debug ("xdp_fuse_access %lx %d", ino, mask);
-
- if (mask != F_OK && (mask & ~(R_OK|W_OK|X_OK)) != 0)
- {
- g_debug ("xdp_fuse_access <- error EINVAL");
- fuse_reply_err (req, EINVAL);
- return;
- }
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- {
- g_debug ("xdp_fuse_access <- error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (inode->type != XDP_INODE_DOC_FILE)
- {
- int dir_mask = 0;
-
- switch (inode->type)
- {
- case XDP_INODE_ROOT:
- case XDP_INODE_BY_APP:
- case XDP_INODE_APP_DIR:
- dir_mask = R_OK | X_OK;
- break;
- case XDP_INODE_APP_DOC_DIR:
- case XDP_INODE_DOC_DIR:
- dir_mask = R_OK | X_OK | W_OK;
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- if (mask != F_OK && ((mask & dir_mask) != mask))
- {
- fuse_reply_err (req, EACCES);
- return;
- }
- }
- else /* A file */
- {
- entry = xdp_lookup_doc (inode->doc_id);
- if (entry == NULL ||
- !app_can_see_doc (entry, inode->app_id))
- {
- g_debug ("xdp_fuse_access <- no entry error ENOENT");
- fuse_reply_err (req, ENOENT);
- return;
- }
-
- if (mask == F_OK)
- {
- if (!app_can_see_doc (entry, inode->app_id))
- {
- fuse_reply_err (req, EACCES);
- return;
- }
- }
- else
- {
- if (((mask & R_OK) && !app_can_see_doc (entry, inode->app_id)) ||
- ((mask & W_OK) && !app_can_write_doc (entry, inode->app_id)) ||
- (mask & X_OK))
- {
- fuse_reply_err (req, EACCES);
- return;
- }
- }
- }
-
- fuse_reply_err (req, 0);
-}
-
-static struct fuse_lowlevel_ops xdp_fuse_oper = {
- .lookup = xdp_fuse_lookup,
- .forget = xdp_fuse_forget,
- .getattr = xdp_fuse_getattr,
- .opendir = xdp_fuse_opendir,
- .readdir = xdp_fuse_readdir,
- .releasedir = xdp_fuse_releasedir,
- .fsyncdir = xdp_fuse_fsyncdir,
- .open = xdp_fuse_open,
- .read = xdp_fuse_read,
- .release = xdp_fuse_release,
- .setattr = xdp_fuse_setattr,
- .write = xdp_fuse_write,
- .write_buf = xdp_fuse_write_buf,
- .fsync = xdp_fuse_fsync,
- .create = xdp_fuse_create,
- .unlink = xdp_fuse_unlink,
- .rename = xdp_fuse_rename,
- .access = xdp_fuse_access,
-};
-
-/* Called when a apps permissions to see a document is changed,
- and with null opt_app_id when the doc is created/removed */
-void
-xdp_fuse_invalidate_doc_app (const char *doc_id,
- const char *opt_app_id)
-{
- g_autoptr(XdpInode) inode = NULL;
- fuse_ino_t ino;
- GList *l;
-
- /* This can happen if fuse is not initialized yet for the very
- first dbus message that activated the service */
- if (main_ch == NULL)
- return;
-
- g_debug ("invalidate %s/%s", doc_id, opt_app_id ? opt_app_id : "*");
-
- AUTOLOCK (inodes);
- ino = get_dir_inode_nr_unlocked (opt_app_id, doc_id);
- inode = xdp_inode_lookup_unlocked (ino);
- if (inode != NULL)
- {
- fuse_lowlevel_notify_inval_inode (main_ch, inode->ino, 0, 0);
- fuse_lowlevel_notify_inval_entry (main_ch, inode->parent->ino,
- inode->filename, strlen (inode->filename));
-
- for (l = inode->children; l != NULL; l = l->next)
- {
- XdpInode *child = l->data;
-
- fuse_lowlevel_notify_inval_inode (main_ch, child->ino, 0, 0);
- if (child->filename != NULL)
- fuse_lowlevel_notify_inval_entry (main_ch, inode->ino,
- child->filename, strlen (child->filename));
- }
- }
-}
-
-char *
-xdp_fuse_lookup_id_for_inode (ino_t ino)
-{
- g_autoptr(XdpInode) inode = NULL;
-
- inode = xdp_inode_lookup (ino);
- if (inode == NULL)
- return NULL;
-
- if (inode->type != XDP_INODE_DOC_FILE ||
- !inode->is_doc)
- return NULL;
-
- return g_strdup (inode->doc_id);
-}
-
-const char *
-xdp_fuse_get_mountpoint (void)
-{
- if (mount_path == NULL)
- mount_path = g_build_filename (g_get_user_runtime_dir (), "doc", NULL);
- return mount_path;
-}
-
-void
-xdp_fuse_exit (void)
-{
- if (session)
- fuse_session_exit (session);
-
- if (fuse_pthread)
- pthread_kill (fuse_pthread, SIGHUP);
-
- if (fuse_thread)
- g_thread_join (fuse_thread);
-}
-
-static gpointer
-xdp_fuse_mainloop (gpointer data)
-{
- fuse_pthread = pthread_self ();
-
- fuse_session_loop_mt (session);
-
- fuse_session_remove_chan (main_ch);
- fuse_session_destroy (session);
- fuse_unmount (mount_path, main_ch);
- return NULL;
-}
-
-gboolean
-xdp_fuse_init (GError **error)
-{
- char *argv[] = { "xdp-fuse", "-osplice_write,splice_move" };
- struct fuse_args args = FUSE_ARGS_INIT (G_N_ELEMENTS (argv), argv);
- struct stat st;
- struct statfs stfs;
- const char *path;
- int statfs_res;
-
- inodes =
- g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
- root_inode = xdp_inode_new (ROOT_INODE, XDP_INODE_ROOT, NULL, "/", NULL, NULL);
- by_app_inode = xdp_inode_new (BY_APP_INODE, XDP_INODE_BY_APP, root_inode, BY_APP_NAME, NULL, NULL);
- dir_to_inode_nr =
- g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- path = xdp_fuse_get_mountpoint ();
- if ((stat (path, &st) == -1 && errno == ENOTCONN) ||
- (((statfs_res = statfs (path, &stfs)) == -1 && errno == ENOTCONN) ||
- (statfs_res == 0 && stfs.f_type == 0x65735546 /* fuse */)))
- {
- int count;
- char *umount_argv[] = { "fusermount", "-u", "-z", (char *) path, NULL };
-
- g_spawn_sync (NULL, umount_argv, NULL, G_SPAWN_SEARCH_PATH,
- NULL, NULL, NULL, NULL, NULL, NULL);
-
- g_usleep (10000); /* 10ms */
- count = 0;
- while (stat (path, &st) == -1 && count < 10)
- g_usleep (10000); /* 10ms */
- }
-
- if (g_mkdir_with_parents (path, 0700))
- {
- g_set_error (error, FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_FAILED,
- "Unable to create dir %s", path);
- return FALSE;
- }
-
- main_ch = fuse_mount (path, &args);
- if (main_ch == NULL)
- {
- g_set_error (error, FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_FAILED, "Can't mount fuse fs");
- return FALSE;
- }
-
- session = fuse_lowlevel_new (&args, &xdp_fuse_oper,
- sizeof (xdp_fuse_oper), NULL);
- if (session == NULL)
- {
- g_set_error (error, FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_FAILED,
- "Can't create fuse session");
- return FALSE;
- }
- fuse_session_add_chan (session, main_ch);
-
- fuse_thread = g_thread_new ("fuse mainloop", xdp_fuse_mainloop, session);
-
- return TRUE;
-}
diff --git a/document-portal/xdp-fuse.h b/document-portal/xdp-fuse.h
deleted file mode 100644
index e208b53d..00000000
--- a/document-portal/xdp-fuse.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef XDP_FUSE_H
-#define XDP_FUSE_H
-
-#include <glib.h>
-#include "flatpak-db.h"
-
-G_BEGIN_DECLS
-
-char ** xdp_list_apps (void);
-char ** xdp_list_docs (void);
-FlatpakDbEntry *xdp_lookup_doc (const char *doc_id);
-
-gboolean xdp_fuse_init (GError **error);
-void xdp_fuse_exit (void);
-const char *xdp_fuse_get_mountpoint (void);
-void xdp_fuse_invalidate_doc_app (const char *doc_id,
- const char *opt_app_id);
-char *xdp_fuse_lookup_id_for_inode (ino_t inode);
-
-
-G_END_DECLS
-
-#endif /* XDP_FUSE_H */
diff --git a/document-portal/xdp-main.c b/document-portal/xdp-main.c
deleted file mode 100644
index a8532b45..00000000
--- a/document-portal/xdp-main.c
+++ /dev/null
@@ -1,1558 +0,0 @@
-#include "config.h"
-
-#include <locale.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <gio/gio.h>
-#include <gio/gunixfdlist.h>
-#include "xdp-dbus.h"
-#include "xdp-util.h"
-#include "flatpak-db.h"
-#include "flatpak-dbus.h"
-#include "flatpak-utils.h"
-#include "flatpak-dir.h"
-#include "flatpak-run.h"
-#include "flatpak-portal-error.h"
-#include "permission-store/permission-store-dbus.h"
-#include "xdp-fuse.h"
-
-#include <sys/eventfd.h>
-
-#define TABLE_NAME "documents"
-
-typedef struct
-{
- char *doc_id;
- int fd;
- char *owner;
- guint flags;
-
- GDBusMethodInvocation *finish_invocation;
-} XdpDocUpdate;
-
-
-static GMainLoop *loop = NULL;
-static FlatpakDb *db = NULL;
-static XdgPermissionStore *permission_store;
-static int daemon_event_fd = -1;
-static int final_exit_status = 0;
-static GError *exit_error = NULL;
-static dev_t fuse_dev = 0;
-static GQueue get_mount_point_invocations = G_QUEUE_INIT;
-static XdpDbusDocuments *dbus_api;
-
-G_LOCK_DEFINE (db);
-
-char **
-xdp_list_apps (void)
-{
- AUTOLOCK (db);
- return flatpak_db_list_apps (db);
-}
-
-char **
-xdp_list_docs (void)
-{
- AUTOLOCK (db);
- return flatpak_db_list_ids (db);
-}
-
-FlatpakDbEntry *
-xdp_lookup_doc (const char *doc_id)
-{
- AUTOLOCK (db);
- return flatpak_db_lookup (db, doc_id);
-}
-
-static gboolean
-persist_entry (FlatpakDbEntry *entry)
-{
- guint32 flags = xdp_entry_get_flags (entry);
-
- return (flags & XDP_ENTRY_FLAG_TRANSIENT) == 0;
-}
-
-static void
-do_set_permissions (FlatpakDbEntry *entry,
- const char *doc_id,
- const char *app_id,
- XdpPermissionFlags perms)
-{
- g_autofree const char **perms_s = xdg_unparse_permissions (perms);
-
- g_autoptr(FlatpakDbEntry) new_entry = NULL;
-
- g_debug ("set_permissions %s %s %x", doc_id, app_id, perms);
-
- new_entry = flatpak_db_entry_set_app_permissions (entry, app_id, perms_s);
- flatpak_db_set_entry (db, doc_id, new_entry);
-
- if (persist_entry (new_entry))
- {
- xdg_permission_store_call_set_permission (permission_store,
- TABLE_NAME,
- FALSE,
- doc_id,
- app_id,
- perms_s,
- NULL,
- NULL, NULL);
- }
-}
-
-static void
-portal_grant_permissions (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- g_autoptr(GError) my_error = NULL;
- const char *target_app_id;
- const char *id;
- g_autofree const char **permissions = NULL;
- XdpPermissionFlags perms;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- g_variant_get (parameters, "(&s&s^a&s)", &id, &target_app_id, &permissions);
-
- {
- AUTOLOCK (db);
-
- entry = flatpak_db_lookup (db, id);
- if (entry == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "No such document: %s", id);
- return;
- }
-
- if (!flatpak_is_valid_name (target_app_id, &my_error))
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "'%s' is not a valid app name: %s", target_app_id, my_error->message);
- return;
- }
-
- perms = xdp_parse_permissions (permissions);
-
- /* Must have grant-permissions and all the newly granted permissions */
- if (!xdp_entry_has_permissions (entry, app_id,
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS | perms))
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not enough permissions");
- return;
- }
-
- do_set_permissions (entry, id, target_app_id,
- perms | xdp_entry_get_permissions (entry, target_app_id));
- }
-
- /* Invalidate with lock dropped to avoid deadlock */
- xdp_fuse_invalidate_doc_app (id, target_app_id);
-
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
-}
-
-static void
-portal_revoke_permissions (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- const char *target_app_id;
- const char *id;
- g_autofree const char **permissions = NULL;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autoptr(GError) my_error = NULL;
- XdpPermissionFlags perms;
-
- g_variant_get (parameters, "(&s&s^a&s)", &id, &target_app_id, &permissions);
-
- {
- AUTOLOCK (db);
-
- entry = flatpak_db_lookup (db, id);
- if (entry == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "No such document: %s", id);
- return;
- }
-
- if (!flatpak_is_valid_name (target_app_id, &my_error))
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "'%s' is not a valid app name: %s", target_app_id, my_error->message);
- return;
- }
-
- perms = xdp_parse_permissions (permissions);
-
- /* Must have grant-permissions, or be itself */
- if (!xdp_entry_has_permissions (entry, app_id,
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS) ||
- strcmp (app_id, target_app_id) == 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not enough permissions");
- return;
- }
-
- do_set_permissions (entry, id, target_app_id,
- ~perms & xdp_entry_get_permissions (entry, target_app_id));
- }
-
- /* Invalidate with lock dropped to avoid deadlock */
- xdp_fuse_invalidate_doc_app (id, target_app_id);
-
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
-}
-
-static void
-portal_delete (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- const char *id;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autofree const char **old_apps = NULL;
- int i;
-
- g_variant_get (parameters, "(s)", &id);
-
- {
- AUTOLOCK (db);
-
- entry = flatpak_db_lookup (db, id);
- if (entry == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "No such document: %s", id);
- return;
- }
-
- if (!xdp_entry_has_permissions (entry, app_id, XDP_PERMISSION_FLAGS_DELETE))
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not enough permissions");
- return;
- }
-
- g_debug ("delete %s", id);
-
- flatpak_db_set_entry (db, id, NULL);
-
- if (persist_entry (entry))
- xdg_permission_store_call_delete (permission_store, TABLE_NAME,
- id, NULL, NULL, NULL);
- }
-
- /* All i/o is done now, so drop the lock so we can invalidate the fuse caches */
- old_apps = flatpak_db_entry_list_apps (entry);
- for (i = 0; old_apps[i] != NULL; i++)
- xdp_fuse_invalidate_doc_app (id, old_apps[i]);
- xdp_fuse_invalidate_doc_app (id, NULL);
-
- /* Now fuse view is up-to-date, so we can return the call */
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
-}
-
-static char *
-do_create_doc (struct stat *parent_st_buf, const char *path, gboolean reuse_existing, gboolean persistent)
-{
- g_autoptr(GVariant) data = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_auto(GStrv) ids = NULL;
- char *id = NULL;
- guint32 flags = 0;
-
- if (!reuse_existing)
- flags |= XDP_ENTRY_FLAG_UNIQUE;
- if (!persistent)
- flags |= XDP_ENTRY_FLAG_TRANSIENT;
- data =
- g_variant_ref_sink (g_variant_new ("(^ayttu)",
- path,
- (guint64) parent_st_buf->st_dev,
- (guint64) parent_st_buf->st_ino,
- flags));
-
- if (reuse_existing)
- {
- ids = flatpak_db_list_ids_by_value (db, data);
-
- if (ids[0] != NULL)
- return g_strdup (ids[0]); /* Reuse pre-existing entry with same path */
- }
-
- while (TRUE)
- {
- g_autoptr(FlatpakDbEntry) existing = NULL;
-
- g_clear_pointer (&id, g_free);
- id = xdp_name_from_id ((guint32) g_random_int ());
- existing = flatpak_db_lookup (db, id);
- if (existing == NULL)
- break;
- }
-
- g_debug ("create_doc %s", id);
-
- entry = flatpak_db_entry_new (data);
- flatpak_db_set_entry (db, id, entry);
-
- if (persistent)
- {
- xdg_permission_store_call_set (permission_store,
- TABLE_NAME,
- TRUE,
- id,
- g_variant_new_array (G_VARIANT_TYPE ("{sas}"), NULL, 0),
- g_variant_new_variant (data),
- NULL, NULL, NULL);
- }
-
- return id;
-}
-
-static gboolean
-validate_fd_common (int fd,
- struct stat *st_buf,
- mode_t st_mode,
- char *path_buffer,
- GError **error)
-{
- g_autofree char *proc_path = NULL;
- ssize_t symlink_size;
- int fd_flags;
-
- proc_path = g_strdup_printf ("/proc/self/fd/%d", fd);
-
- if (fd == -1 ||
- /* Must be able to get fd flags */
- (fd_flags = fcntl (fd, F_GETFL)) == -1 ||
- /* Must be O_PATH */
- ((fd_flags & O_PATH) != O_PATH) ||
- /* Must not be O_NOFOLLOW (because we want the target file) */
- ((fd_flags & O_NOFOLLOW) == O_NOFOLLOW) ||
- /* Must be able to fstat */
- fstat (fd, st_buf) < 0 ||
- /* Must be a regular file or directory (depending on use) */
- (st_buf->st_mode & S_IFMT) != st_mode ||
- /* Must be able to read path from /proc/self/fd */
- /* This is an absolute and (at least at open time) symlink-expanded path */
- (symlink_size = readlink (proc_path, path_buffer, PATH_MAX)) < 0)
- {
- g_set_error (error,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return FALSE;
- }
-
- path_buffer[symlink_size] = 0;
- return TRUE;
-}
-
-static gboolean
-validate_parent_dir (const char *path,
- struct stat *st_buf,
- struct stat *real_parent_st_buf,
- GError **error)
-{
- g_autofree char *dirname = NULL;
- g_autofree char *name = NULL;
- glnx_autofd int dir_fd = -1;
- struct stat real_st_buf;
-
- /* We open the parent directory and do the stat in that, so that we have
- * trustworthy parent dev/ino for later verification. Otherwise the caller
- * could later replace a parent with a symlink and make us read some other file
- */
- dirname = g_path_get_dirname (path);
- name = g_path_get_basename (path);
- dir_fd = open (dirname, O_CLOEXEC | O_PATH);
-
- if (dir_fd < 0 ||
- fstat (dir_fd, real_parent_st_buf) < 0 ||
- fstatat (dir_fd, name, &real_st_buf, AT_SYMLINK_NOFOLLOW) < 0 ||
- st_buf->st_dev != real_st_buf.st_dev ||
- st_buf->st_ino != real_st_buf.st_ino)
- {
- /* Don't leak any info about real file path existence, etc */
- g_set_error (error,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-validate_fd (int fd,
- GKeyFile *app_info,
- struct stat *st_buf,
- struct stat *real_parent_st_buf,
- char *path_buffer,
- GError **error)
-{
- g_autofree char *app_path = NULL;
- g_autofree char *runtime_path = NULL;
-
- if (!validate_fd_common (fd, st_buf, S_IFREG, path_buffer, error))
- return FALSE;
-
- /* For apps we translate /app and /usr to the installed locations.
- Also, we need to rewrite to drop the /newroot prefix added by
- bubblewrap for other files to work. See
- https://github.com/projectatomic/bubblewrap/pull/172
- for a bit more information on the /newroot issue.
- */
- app_path = g_key_file_get_string (app_info, FLATPAK_METADATA_GROUP_INSTANCE,
- FLATPAK_METADATA_KEY_APP_PATH, NULL);
- runtime_path = g_key_file_get_string (app_info,
- FLATPAK_METADATA_GROUP_INSTANCE,
- FLATPAK_METADATA_KEY_RUNTIME_PATH,
- NULL);
- if (app_path != NULL || runtime_path != NULL)
- {
- gboolean had_newroot_prefix = g_str_has_prefix (path_buffer, "/newroot/");
- const char *tmp_path_buf;
- if (had_newroot_prefix)
- tmp_path_buf = path_buffer + strlen ("/newroot");
- else
- tmp_path_buf = path_buffer;
- if (app_path != NULL &&
- g_str_has_prefix (tmp_path_buf, "/app/"))
- {
- const char *rel_path = tmp_path_buf + strlen ("/app/");
- g_autofree char *real_path = g_build_filename (app_path, rel_path, NULL);
- strncpy (path_buffer, real_path, PATH_MAX);
- }
- else if (runtime_path != NULL &&
- g_str_has_prefix (tmp_path_buf, "/usr/"))
- {
- const char *rel_path = tmp_path_buf + strlen ("/usr/");
- g_autofree char *real_path = g_build_filename (runtime_path, rel_path, NULL);
- strncpy (path_buffer, real_path, PATH_MAX);
- }
- else if (g_str_has_prefix (tmp_path_buf, "/run/host/usr/"))
- {
- const char *rel_path = tmp_path_buf + strlen ("/run/host/usr/");
- g_autofree char *real_path = g_build_filename ("/usr", rel_path, NULL);
- strncpy (path_buffer, real_path, PATH_MAX);
- }
- else if (g_str_has_prefix (tmp_path_buf, "/run/host/etc/"))
- {
- const char *rel_path = tmp_path_buf + strlen ("/run/host/etc/");
- g_autofree char *real_path = g_build_filename ("/etc", rel_path, NULL);
- strncpy (path_buffer, real_path, PATH_MAX);
- }
- else if (had_newroot_prefix)
- {
- /* Create a separate copy to avoid memcpy-type issues where
- * source and destination overlap.
- */
- const char *rel_path = strdupa (tmp_path_buf);
- g_strlcpy (path_buffer, rel_path, PATH_MAX);
- }
- }
-
- if (!validate_parent_dir (path_buffer, st_buf, real_parent_st_buf, error))
- return FALSE;
-
- return TRUE;
-}
-
-static char *
-verify_existing_document (struct stat *st_buf, gboolean reuse_existing)
-{
- g_autoptr(FlatpakDbEntry) old_entry = NULL;
- g_autofree char *id = NULL;
-
- g_assert (st_buf->st_dev == fuse_dev);
-
- /* The passed in fd is on the fuse filesystem itself */
- id = xdp_fuse_lookup_id_for_inode (st_buf->st_ino);
- g_debug ("path on fuse, id %s", id);
- if (id == NULL)
- return NULL;
-
- /* Don't lock the db before doing the fuse call above, because it takes takes a lock
- that can block something calling back, causing a deadlock on the db lock */
- AUTOLOCK (db);
-
- /* If the entry doesn't exist anymore, fail. Also fail if not
- * reuse_existing, because otherwise the user could use this to
- * get a copy with permissions and thus escape later permission
- * revocations
- */
- old_entry = flatpak_db_lookup (db, id);
- if (old_entry == NULL || !reuse_existing)
- return NULL;
-
- return g_steal_pointer (&id);
-}
-
-static void
-portal_add (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- GDBusMessage *message;
- GUnixFDList *fd_list;
- g_autofree char *id = NULL;
- int fd_id, fd, fds_len;
- char path_buffer[PATH_MAX + 1];
- const int *fds;
- struct stat st_buf, real_parent_st_buf;
- gboolean reuse_existing, persistent;
- GError *error = NULL;
- GKeyFile *app_info = g_object_get_data (G_OBJECT (invocation), "app-info");
-
- g_variant_get (parameters, "(hbb)", &fd_id, &reuse_existing, &persistent);
-
- message = g_dbus_method_invocation_get_message (invocation);
- fd_list = g_dbus_message_get_unix_fd_list (message);
-
- fd = -1;
- if (fd_list != NULL)
- {
- fds = g_unix_fd_list_peek_fds (fd_list, &fds_len);
- if (fd_id < fds_len)
- fd = fds[fd_id];
- }
-
- if (!validate_fd (fd, app_info, &st_buf, &real_parent_st_buf, path_buffer, &error))
- {
- g_dbus_method_invocation_take_error (invocation, error);
- return;
- }
-
- if (st_buf.st_dev == fuse_dev)
- {
- /* The passed in fd is on the fuse filesystem itself */
- id = verify_existing_document (&st_buf, reuse_existing);
- if (id == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return;
- }
- }
- else
- {
- {
- AUTOLOCK (db);
-
- id = do_create_doc (&real_parent_st_buf, path_buffer, reuse_existing, persistent);
-
- if (app_id[0] != '\0')
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (db, id);
- XdpPermissionFlags perms =
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS |
- XDP_PERMISSION_FLAGS_READ |
- XDP_PERMISSION_FLAGS_WRITE;
-
- /* If its a unique one its safe for the creator to
- delete it at will */
- if (!reuse_existing)
- perms |= XDP_PERMISSION_FLAGS_DELETE;
-
- do_set_permissions (entry, id, app_id, perms);
- }
- }
-
- /* Invalidate with lock dropped to avoid deadlock */
- xdp_fuse_invalidate_doc_app (id, NULL);
- if (app_id[0] != '\0')
- xdp_fuse_invalidate_doc_app (id, app_id);
- }
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(s)", id));
-}
-
-static gboolean
-app_has_file_access (const char *target_app_id,
- XdpPermissionFlags target_perms,
- const char *path)
-{
- g_autoptr(FlatpakContext) app_context = NULL;
- g_autoptr(FlatpakExports) app_exports = NULL;
- FlatpakFilesystemMode mode = 0;
-
- if (target_app_id == NULL || target_app_id[0] == '\0')
- return FALSE;
-
- app_context = flatpak_context_load_for_app (target_app_id, NULL);
- if (app_context == NULL)
- return FALSE;
-
- app_exports = flatpak_context_get_exports (app_context, target_app_id);
- if (app_exports == NULL)
- return FALSE;
-
- mode = flatpak_exports_path_get_mode (app_exports, path);
-
- if (mode == FLATPAK_FILESYSTEM_MODE_READ_WRITE)
- return TRUE;
-
- if ((mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY) &&
- ((target_perms & XDP_PERMISSION_FLAGS_WRITE) == 0))
- return TRUE;
-
- return FALSE;
-}
-
-static void
-portal_add_full (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- GDBusMessage *message;
- GUnixFDList *fd_list;
- char *id;
- int fd_id, fd, fds_len;
- char path_buffer[PATH_MAX + 1];
- const int *fds = NULL;
- struct stat st_buf;
- gboolean reuse_existing, persistent, as_needed_by_app;
- GError *error = NULL;
- guint32 flags = 0;
- GKeyFile *app_info = g_object_get_data (G_OBJECT (invocation), "app-info");
- g_autoptr(GVariant) array = NULL;
- const char *target_app_id;
- g_autofree const char **permissions = NULL;
- g_autoptr(GPtrArray) ids = g_ptr_array_new_with_free_func (g_free);
- g_autoptr(GPtrArray) paths = g_ptr_array_new_with_free_func (g_free);
- g_autofree struct stat *real_parent_st_bufs = NULL;
- int i;
- gsize n_args;
- XdpPermissionFlags target_perms;
- GVariantBuilder builder;
-
- g_variant_get (parameters, "(@ahus^a&s)",
- &array, &flags, &target_app_id, &permissions);
-
- if ((flags & ~XDP_ADD_FLAGS_FLAGS_ALL) != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid flags");
- return;
- }
-
- reuse_existing = (flags & XDP_ADD_FLAGS_REUSE_EXISTING) != 0;
- persistent = (flags & XDP_ADD_FLAGS_PERSISTENT) != 0;
- as_needed_by_app = (flags & XDP_ADD_FLAGS_AS_NEEDED_BY_APP) != 0;
-
- target_perms = xdp_parse_permissions (permissions);
-
- n_args = g_variant_n_children (array);
- g_ptr_array_set_size (ids, n_args + 1);
- g_ptr_array_set_size (paths, n_args + 1);
- real_parent_st_bufs = g_new0 (struct stat, n_args);
-
- message = g_dbus_method_invocation_get_message (invocation);
- fd_list = g_dbus_message_get_unix_fd_list (message);
- if (fd_list != NULL)
- fds = g_unix_fd_list_peek_fds (fd_list, &fds_len);
-
- for (i = 0; i < n_args; i++)
- {
- g_variant_get_child (array, i, "h", &fd_id);
-
- fd = -1;
- if (fds != NULL && fd_id < fds_len)
- fd = fds[fd_id];
-
- if (!validate_fd (fd, app_info, &st_buf, &real_parent_st_bufs[i], path_buffer, &error))
- {
- g_dbus_method_invocation_take_error (invocation, error);
- return;
- }
-
- g_ptr_array_index(paths,i) = g_strdup (path_buffer);
-
- if (st_buf.st_dev == fuse_dev)
- {
- /* The passed in fd is on the fuse filesystem itself */
- id = verify_existing_document (&st_buf, reuse_existing);
- if (id == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return;
- }
- g_ptr_array_index(ids,i) = id;
- }
- }
-
- {
- XdpPermissionFlags caller_perms =
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS |
- XDP_PERMISSION_FLAGS_READ |
- XDP_PERMISSION_FLAGS_WRITE;
-
- /* If its a unique one its safe for the creator to
- delete it at will */
- if (!reuse_existing)
- caller_perms |= XDP_PERMISSION_FLAGS_DELETE;
-
- AUTOLOCK (db); /* Lock once for all ops */
-
- for (i = 0; i < n_args; i++)
- {
- const char *path = g_ptr_array_index(paths,i);
- g_assert (path != NULL);
-
- if (as_needed_by_app &&
- app_has_file_access (target_app_id, target_perms, path))
- {
- g_free (g_ptr_array_index(ids,i));
- g_ptr_array_index(ids,i) = g_strdup ("");
- continue;
- }
-
- if (g_ptr_array_index(ids,i) == NULL)
- {
- id = do_create_doc (&real_parent_st_bufs[i], path, reuse_existing, persistent);
- g_ptr_array_index(ids,i) = id;
-
- if (app_id[0] != '\0' && strcmp (app_id, target_app_id) != 0)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (db, id);;
- do_set_permissions (entry, id, app_id, caller_perms);
- }
-
- if (target_app_id[0] != '\0' && target_perms != 0)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (db, id);
- do_set_permissions (entry, id, target_app_id, target_perms);
- }
- }
- }
- }
-
- /* Invalidate with lock dropped to avoid deadlock */
- for (i = 0; i < n_args; i++)
- {
- id = g_ptr_array_index (ids,i);
- g_assert (id != NULL);
-
- if (*id == 0)
- continue;
-
- xdp_fuse_invalidate_doc_app (id, NULL);
- if (app_id[0] != '\0')
- xdp_fuse_invalidate_doc_app (id, app_id);
- if (target_app_id[0] != '\0' && target_perms != 0)
- xdp_fuse_invalidate_doc_app (id, target_app_id);
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}", "mountpoint",
- g_variant_new_bytestring (xdp_fuse_get_mountpoint ()));
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(^as@a{sv})",
- (char **)ids->pdata,
- g_variant_builder_end (&builder)));
-}
-
-static void
-portal_add_named_full (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- GDBusMessage *message;
- GUnixFDList *fd_list;
- int parent_fd_id, parent_fd, fds_len;
- char parent_path_buffer[PATH_MAX + 1];
- const int *fds = NULL;
- struct stat parent_st_buf;
- gboolean reuse_existing, persistent, as_needed_by_app;
- GError *error = NULL;
- guint32 flags = 0;
- const char *filename;
- const char *target_app_id;
- g_autofree const char **permissions = NULL;
- g_autofree char *id = NULL;
- g_autofree char *path = NULL;
- XdpPermissionFlags target_perms;
- GVariantBuilder builder;
- g_autoptr(GVariant) filename_v = NULL;
-
- g_variant_get (parameters, "(h@ayus^a&s)", &parent_fd_id, &filename_v, &flags, &target_app_id, &permissions);
- filename = g_variant_get_bytestring (filename_v);
-
- /* This is only allowed from the host, or else we could leak existence of files */
- if (*app_id != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not enough permissions");
- return;
- }
-
- if ((flags & ~XDP_ADD_FLAGS_FLAGS_ALL) != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid flags");
- return;
- }
-
- reuse_existing = (flags & XDP_ADD_FLAGS_REUSE_EXISTING) != 0;
- persistent = (flags & XDP_ADD_FLAGS_PERSISTENT) != 0;
- as_needed_by_app = (flags & XDP_ADD_FLAGS_AS_NEEDED_BY_APP) != 0;
-
- target_perms = xdp_parse_permissions (permissions);
-
- message = g_dbus_method_invocation_get_message (invocation);
- fd_list = g_dbus_message_get_unix_fd_list (message);
-
- parent_fd = -1;
- if (fd_list != NULL)
- {
- fds = g_unix_fd_list_peek_fds (fd_list, &fds_len);
- if (parent_fd_id < fds_len)
- parent_fd = fds[parent_fd_id];
- }
-
- if (strchr (filename, '/') != NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid filename passed");
- return;
- }
-
- if (!validate_fd_common (parent_fd, &parent_st_buf, S_IFDIR, parent_path_buffer, &error))
- {
- g_dbus_method_invocation_return_gerror (invocation, error);
- return;
- }
-
- if (parent_st_buf.st_dev == fuse_dev)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return;
- }
-
- path = g_build_filename (parent_path_buffer, filename, NULL);
-
- g_debug ("portal_add_named_full %s", path);
-
- {
- XdpPermissionFlags caller_perms =
- XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS |
- XDP_PERMISSION_FLAGS_READ |
- XDP_PERMISSION_FLAGS_WRITE;
-
- /* If its a unique one its safe for the creator to
- delete it at will */
- if (!reuse_existing)
- caller_perms |= XDP_PERMISSION_FLAGS_DELETE;
-
- AUTOLOCK (db);
-
- if (as_needed_by_app &&
- app_has_file_access (target_app_id, target_perms, path))
- {
- id = g_strdup ("");
- }
- else
- {
- id = do_create_doc (&parent_st_buf, path, reuse_existing, persistent);
-
- if (app_id[0] != '\0' && strcmp (app_id, target_app_id) != 0)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (db, id);;
- do_set_permissions (entry, id, app_id, caller_perms);
- }
-
- if (target_app_id[0] != '\0' && target_perms != 0)
- {
- g_autoptr(FlatpakDbEntry) entry = flatpak_db_lookup (db, id);
- do_set_permissions (entry, id, target_app_id, target_perms);
- }
- }
- }
-
- /* Invalidate with lock dropped to avoid deadlock */
- g_assert (id != NULL);
-
- if (*id != 0)
- {
- xdp_fuse_invalidate_doc_app (id, NULL);
- if (app_id[0] != '\0')
- xdp_fuse_invalidate_doc_app (id, app_id);
- if (target_app_id[0] != '\0' && target_perms != 0)
- xdp_fuse_invalidate_doc_app (id, target_app_id);
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}", "mountpoint",
- g_variant_new_bytestring (xdp_fuse_get_mountpoint ()));
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(s@a{sv})",
- id,
- g_variant_builder_end (&builder)));
-}
-
-static void
-portal_add_named (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- GDBusMessage *message;
- GUnixFDList *fd_list;
- g_autofree char *id = NULL;
- int parent_fd_id, parent_fd, fds_len;
- const int *fds;
- char parent_path_buffer[PATH_MAX + 1];
- g_autofree char *path = NULL;
- struct stat parent_st_buf;
- const char *filename;
- gboolean reuse_existing, persistent;
- g_autoptr(GError) error = NULL;
-
- g_autoptr(GVariant) filename_v = NULL;
-
- g_variant_get (parameters, "(h@aybb)", &parent_fd_id, &filename_v, &reuse_existing, &persistent);
- filename = g_variant_get_bytestring (filename_v);
-
- /* This is only allowed from the host, or else we could leak existence of files */
- if (*app_id != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not enough permissions");
- return;
- }
-
- message = g_dbus_method_invocation_get_message (invocation);
- fd_list = g_dbus_message_get_unix_fd_list (message);
-
- parent_fd = -1;
- if (fd_list != NULL)
- {
- fds = g_unix_fd_list_peek_fds (fd_list, &fds_len);
- if (parent_fd_id < fds_len)
- parent_fd = fds[parent_fd_id];
- }
-
- if (strchr (filename, '/') != NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid filename passed");
- return;
- }
-
- if (!validate_fd_common (parent_fd, &parent_st_buf, S_IFDIR, parent_path_buffer, &error))
- {
- g_dbus_method_invocation_return_gerror (invocation, error);
- return;
- }
-
- if (parent_st_buf.st_dev == fuse_dev)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid fd passed");
- return;
- }
-
- path = g_build_filename (parent_path_buffer, filename, NULL);
-
- g_debug ("portal_add_named %s", path);
-
- AUTOLOCK (db);
-
- id = do_create_doc (&parent_st_buf, path, reuse_existing, persistent);
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(s)", id));
-}
-
-
-typedef void (*PortalMethod) (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id);
-
-static void
-got_app_id_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (source_object);
-
- g_autoptr(GError) error = NULL;
- g_autoptr(GKeyFile) app_info = NULL;
- g_autofree char *app_id = NULL;
- PortalMethod portal_method = user_data;
-
- app_info = flatpak_invocation_lookup_app_info_finish (invocation, res, &error);
- if (app_info != NULL)
- app_id = g_key_file_get_string (app_info,
- FLATPAK_METADATA_GROUP_APPLICATION,
- FLATPAK_METADATA_KEY_NAME, &error);
-
- if (app_id == NULL)
- g_dbus_method_invocation_return_gerror (invocation, error);
- else
- {
- g_object_set_data_full (G_OBJECT (invocation), "app-info", g_steal_pointer (&app_info), (GDestroyNotify)g_key_file_unref);
- portal_method (invocation, g_dbus_method_invocation_get_parameters (invocation), app_id);
- }
-}
-
-static gboolean
-handle_method (GCallback method_callback,
- GDBusMethodInvocation *invocation)
-{
- flatpak_invocation_lookup_app_info (invocation, NULL, got_app_id_cb, method_callback);
-
- return TRUE;
-}
-
-static gboolean
-handle_get_mount_point (XdpDbusDocuments *object, GDBusMethodInvocation *invocation)
-{
- if (fuse_dev == 0)
- {
- /* We mustn't reply to this until the FUSE mount point is open for
- * business. */
- g_queue_push_tail (&get_mount_point_invocations, g_object_ref (invocation));
- return TRUE;
- }
-
- xdp_dbus_documents_complete_get_mount_point (object, invocation, xdp_fuse_get_mountpoint ());
- return TRUE;
-}
-
-static gboolean
-portal_lookup (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- const char *filename;
- char path_buffer[PATH_MAX + 1];
- glnx_autofd int fd = -1;
- struct stat st_buf, real_parent_st_buf;
- g_auto(GStrv) ids = NULL;
- g_autofree char *id = NULL;
- GError *error = NULL;
- GKeyFile *app_info = g_object_get_data (G_OBJECT (invocation), "app-info");
-
- if (strcmp (app_id, "") != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not allowed in sandbox");
- return TRUE;
- }
-
- g_variant_get (parameters, "(^&ay)", &filename);
-
- fd = open (filename, O_PATH | O_CLOEXEC);
- if (fd == -1)
- {
- glnx_set_error_from_errno (&error);
- g_dbus_method_invocation_take_error (invocation, error);
- return TRUE;
- }
-
- if (!validate_fd (fd, app_info, &st_buf, &real_parent_st_buf, path_buffer, &error))
- {
- g_dbus_method_invocation_take_error (invocation, error);
- return TRUE;
- }
-
- if (st_buf.st_dev == fuse_dev)
- {
- /* The passed in fd is on the fuse filesystem itself */
- id = xdp_fuse_lookup_id_for_inode (st_buf.st_ino);
- g_debug ("path on fuse, id %s", id);
- }
- else
- {
- g_autoptr(GVariant) data = NULL;
-
- data = g_variant_ref_sink (g_variant_new ("(^ayttu)",
- path_buffer,
- (guint64)real_parent_st_buf.st_dev,
- (guint64)real_parent_st_buf.st_ino,
- 0));
- ids = flatpak_db_list_ids_by_value (db, data);
- if (ids[0] != NULL)
- id = g_strdup (ids[0]);
- }
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(s)", id ? id : ""));
-
- return TRUE;
-}
-
-static GVariant *
-get_app_permissions (FlatpakDbEntry *entry)
-{
- g_autofree const char **apps = NULL;
- GVariantBuilder builder;
- int i;
-
- apps = flatpak_db_entry_list_apps (entry);
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sas}"));
-
- for (i = 0; apps[i] != NULL; i++)
- {
- g_autofree const char **permissions = flatpak_db_entry_list_permissions (entry, apps[i]);
- g_variant_builder_add_value (&builder,
- g_variant_new ("{s^as}", apps[i], permissions));
- }
-
- return g_variant_builder_end (&builder);
-}
-
-static GVariant *
-get_path (FlatpakDbEntry *entry)
-{
- g_autoptr (GVariant) data = flatpak_db_entry_get_data (entry);
- const char *path;
-
- g_variant_get (data, "(^ayttu)", &path, NULL, NULL, NULL);
- return g_variant_new_bytestring (path);
-}
-
-static gboolean
-portal_info (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- const char *id = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- if (strcmp (app_id, "") != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not allowed in sandbox");
- return TRUE;
- }
-
- g_variant_get (parameters, "(&s)", &id);
-
- AUTOLOCK (db);
-
- entry = flatpak_db_lookup (db, id);
-
- if (!entry)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
- "Invalid ID passed");
- return TRUE;
- }
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(@ay@a{sas})",
- get_path (entry),
- get_app_permissions (entry)));
-
- return TRUE;
-}
-
-static gboolean
-portal_list (GDBusMethodInvocation *invocation,
- GVariant *parameters,
- const char *app_id)
-{
- g_auto(GStrv) ids = NULL;
- GVariantBuilder builder;
- int i;
-
- if (strcmp (app_id, "") != 0)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
- "Not allowed in sandbox");
- return TRUE;
- }
-
- g_variant_get (parameters, "(&s)", &app_id);
-
- AUTOLOCK (db);
-
- if (strcmp (app_id, "") == 0)
- ids = flatpak_db_list_ids (db);
- else
- ids = flatpak_db_list_ids_by_app (db, app_id);
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{say}"));
- for (i = 0; ids[i]; i++)
- {
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- entry = flatpak_db_lookup (db, ids[i]);
-
- g_variant_builder_add (&builder, "{s@ay}", ids[i], get_path (entry));
- }
-
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(@a{say})",
- g_variant_builder_end (&builder)));
-
- return TRUE;
-}
-
-static void
-on_bus_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- GError *error = NULL;
-
- dbus_api = xdp_dbus_documents_skeleton_new ();
-
- xdp_dbus_documents_set_version (XDP_DBUS_DOCUMENTS (dbus_api), 3);
-
- g_signal_connect_swapped (dbus_api, "handle-get-mount-point", G_CALLBACK (handle_get_mount_point), NULL);
- g_signal_connect_swapped (dbus_api, "handle-add", G_CALLBACK (handle_method), portal_add);
- g_signal_connect_swapped (dbus_api, "handle-add-named", G_CALLBACK (handle_method), portal_add_named);
- g_signal_connect_swapped (dbus_api, "handle-add-full", G_CALLBACK (handle_method), portal_add_full);
- g_signal_connect_swapped (dbus_api, "handle-add-named-full", G_CALLBACK (handle_method), portal_add_named_full);
- g_signal_connect_swapped (dbus_api, "handle-grant-permissions", G_CALLBACK (handle_method), portal_grant_permissions);
- g_signal_connect_swapped (dbus_api, "handle-revoke-permissions", G_CALLBACK (handle_method), portal_revoke_permissions);
- g_signal_connect_swapped (dbus_api, "handle-delete", G_CALLBACK (handle_method), portal_delete);
- g_signal_connect_swapped (dbus_api, "handle-lookup", G_CALLBACK (handle_method), portal_lookup);
- g_signal_connect_swapped (dbus_api, "handle-info", G_CALLBACK (handle_method), portal_info);
- g_signal_connect_swapped (dbus_api, "handle-list", G_CALLBACK (handle_method), portal_list);
-
- flatpak_connection_track_name_owners (connection);
-
- if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (dbus_api),
- connection,
- "/org/freedesktop/portal/documents",
- &error))
- {
- g_warning ("error: %s", error->message);
- g_error_free (error);
- }
-}
-
-static void
-daemon_report_done (int status)
-{
- if (daemon_event_fd != -1)
- {
- guint64 counter;
-
- counter = status + 1;
- if (write (daemon_event_fd, &counter, sizeof (counter)) < 0)
- g_critical ("Unable to report exit status: %s", g_strerror (errno));
-
- daemon_event_fd = -1;
- }
-}
-
-static void
-do_exit (int status)
-{
- daemon_report_done (status);
- exit (status);
-}
-
-static void
-on_name_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- struct stat stbuf;
- gpointer invocation;
-
- g_debug ("%s acquired", name);
-
- if (!xdp_fuse_init (&exit_error))
- {
- final_exit_status = 6;
- g_printerr ("fuse init failed: %s", exit_error->message);
- g_main_loop_quit (loop);
- return;
- }
-
- if (stat (xdp_fuse_get_mountpoint (), &stbuf) != 0)
- {
- g_set_error (&exit_error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "fuse stat failed: %s", g_strerror (errno));
- final_exit_status = 7;
- g_printerr ("fuse stat failed: %s", g_strerror (errno));
- g_main_loop_quit (loop);
- return;
- }
-
- fuse_dev = stbuf.st_dev;
-
- while ((invocation = g_queue_pop_head (&get_mount_point_invocations)) != NULL)
- {
- xdp_dbus_documents_complete_get_mount_point (dbus_api, invocation, xdp_fuse_get_mountpoint ());
- g_object_unref (invocation);
- }
-
- daemon_report_done (0);
-}
-
-static void
-on_name_lost (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- g_debug ("%s lost", name);
-
- if (final_exit_status == 0)
- final_exit_status = 20;
-
- if (exit_error == NULL)
- g_set_error (&exit_error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "D-Bus name \"%s\" lost", name);
-
- g_main_loop_quit (loop);
-}
-
-static void
-exit_handler (int sig)
-{
- /* We cannot set exit_error here, because malloc() in a signal handler
- * is undefined behaviour. Rely on main() coping gracefully with
- * that. */
- g_main_loop_quit (loop);
-}
-
-static void
-session_bus_closed (GDBusConnection *connection,
- gboolean remote_peer_vanished,
- GError *bus_error)
-{
- if (exit_error == NULL)
- g_set_error (&exit_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE, "Disconnected from session bus");
-
- g_main_loop_quit (loop);
-}
-
-static int
-set_one_signal_handler (int sig,
- void (*handler)(int),
- int remove)
-{
- struct sigaction sa;
- struct sigaction old_sa;
-
- memset (&sa, 0, sizeof (struct sigaction));
- sa.sa_handler = remove ? SIG_DFL : handler;
- sigemptyset (&(sa.sa_mask));
- sa.sa_flags = 0;
-
- if (sigaction (sig, NULL, &old_sa) == -1)
- {
- g_warning ("cannot get old signal handler");
- return -1;
- }
-
- if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
- sigaction (sig, &sa, NULL) == -1)
- {
- g_warning ("cannot set signal handler");
- return -1;
- }
-
- return 0;
-}
-
-static gboolean opt_verbose;
-static gboolean opt_daemon;
-static gboolean opt_replace;
-static gboolean opt_version;
-
-static GOptionEntry entries[] = {
- { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information", NULL },
- { "daemon", 'd', 0, G_OPTION_ARG_NONE, &opt_daemon, "Run in background", NULL },
- { "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace", NULL },
- { "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print version and exit", NULL },
- { NULL }
-};
-
-static void
-message_handler (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data)
-{
- /* Make this look like normal console output */
- if (log_level & G_LOG_LEVEL_DEBUG)
- printf ("XDP: %s\n", message);
- else
- printf ("%s: %s\n", g_get_prgname (), message);
-}
-
-static void
-printerr_handler (const gchar *string)
-{
- const char *prefix = "";
- const char *suffix = "";
- if (flatpak_fancy_output ())
- {
- prefix = FLATPAK_ANSI_RED FLATPAK_ANSI_BOLD_ON;
- suffix = FLATPAK_ANSI_BOLD_OFF FLATPAK_ANSI_COLOR_RESET;
- }
- fprintf (stderr, "%serror: %s%s\n", prefix, suffix, string);
-}
-
-int
-main (int argc,
- char **argv)
-{
- guint owner_id;
-
- g_autoptr(GError) error = NULL;
- g_autofree char *path = NULL;
- GDBusConnection *session_bus;
- GOptionContext *context;
- GDBusMethodInvocation *invocation;
-
- setlocale (LC_ALL, "");
-
- /* Avoid even loading gvfs to avoid accidental confusion */
- g_setenv ("GIO_USE_VFS", "local", TRUE);
-
- flatpak_migrate_from_xdg_app ();
-
- g_set_printerr_handler (printerr_handler);
-
- context = g_option_context_new ("- document portal");
- g_option_context_add_main_entries (context, entries, NULL);
- if (!g_option_context_parse (context, &argc, &argv, &error))
- {
- g_printerr ("Option parsing failed: %s", error->message);
- return 1;
- }
-
- if (opt_version)
- {
- g_print ("%s\n", PACKAGE_STRING);
- exit (EXIT_SUCCESS);
- }
-
- if (opt_daemon)
- {
- pid_t pid;
- ssize_t read_res;
-
- daemon_event_fd = eventfd (0, EFD_CLOEXEC);
- pid = fork ();
- if (pid != 0)
- {
- guint64 counter;
-
- read_res = read (daemon_event_fd, &counter, sizeof (counter));
- if (read_res != 8)
- exit (1);
- exit (counter - 1);
- }
- }
-
- if (opt_verbose)
- g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL);
-
- g_set_prgname (argv[0]);
-
- loop = g_main_loop_new (NULL, FALSE);
-
- path = g_build_filename (g_get_user_data_dir (), "flatpak/db", TABLE_NAME, NULL);
- db = flatpak_db_new (path, FALSE, &error);
- if (db == NULL)
- {
- g_printerr ("Failed to load db: %s", error->message);
- do_exit (2);
- }
-
- session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
- if (session_bus == NULL)
- {
- g_printerr ("No session bus: %s", error->message);
- do_exit (3);
- }
-
- permission_store = xdg_permission_store_proxy_new_sync (session_bus, G_DBUS_PROXY_FLAGS_NONE,
- "org.freedesktop.impl.portal.PermissionStore",
- "/org/freedesktop/impl/portal/PermissionStore",
- NULL, &error);
- if (permission_store == NULL)
- {
- g_print ("No permission store: %s", error->message);
- do_exit (4);
- }
-
- /* We want do do our custom post-mainloop exit */
- g_dbus_connection_set_exit_on_close (session_bus, FALSE);
-
- g_signal_connect (session_bus, "closed", G_CALLBACK (session_bus_closed), NULL);
-
- if (set_one_signal_handler (SIGHUP, exit_handler, 0) == -1 ||
- set_one_signal_handler (SIGINT, exit_handler, 0) == -1 ||
- set_one_signal_handler (SIGTERM, exit_handler, 0) == -1 ||
- set_one_signal_handler (SIGPIPE, SIG_IGN, 0) == -1)
- do_exit (5);
-
- owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
- "org.freedesktop.portal.Documents",
- G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
- on_bus_acquired,
- on_name_acquired,
- on_name_lost,
- NULL,
- NULL);
-
- g_main_loop_run (loop);
-
- while ((invocation = g_queue_pop_head (&get_mount_point_invocations)) != NULL)
- {
- if (exit_error != NULL)
- g_dbus_method_invocation_return_gerror (invocation, exit_error);
- else
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Terminated");
-
- g_object_unref (invocation);
- }
-
- xdp_fuse_exit ();
-
- g_bus_unown_name (owner_id);
-
- do_exit (final_exit_status);
-
- return 0;
-}
diff --git a/document-portal/xdp-util.c b/document-portal/xdp-util.c
deleted file mode 100644
index 0f5f0854..00000000
--- a/document-portal/xdp-util.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "config.h"
-#include <string.h>
-#include <errno.h>
-#include <gio/gio.h>
-#include "flatpak-portal-error.h"
-#include "xdp-util.h"
-
-const char **
-xdg_unparse_permissions (XdpPermissionFlags permissions)
-{
- GPtrArray *array;
-
- array = g_ptr_array_new ();
-
- if (permissions & XDP_PERMISSION_FLAGS_READ)
- g_ptr_array_add (array, "read");
- if (permissions & XDP_PERMISSION_FLAGS_WRITE)
- g_ptr_array_add (array, "write");
- if (permissions & XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS)
- g_ptr_array_add (array, "grant-permissions");
- if (permissions & XDP_PERMISSION_FLAGS_DELETE)
- g_ptr_array_add (array, "delete");
-
- g_ptr_array_add (array, NULL);
- return (const char **) g_ptr_array_free (array, FALSE);
-}
-
-XdpPermissionFlags
-xdp_parse_permissions (const char **permissions)
-{
- XdpPermissionFlags perms;
- int i;
-
- perms = 0;
- for (i = 0; permissions[i]; i++)
- {
- if (strcmp (permissions[i], "read") == 0)
- perms |= XDP_PERMISSION_FLAGS_READ;
- else if (strcmp (permissions[i], "write") == 0)
- perms |= XDP_PERMISSION_FLAGS_WRITE;
- else if (strcmp (permissions[i], "grant-permissions") == 0)
- perms |= XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS;
- else if (strcmp (permissions[i], "delete") == 0)
- perms |= XDP_PERMISSION_FLAGS_DELETE;
- else
- g_warning ("No such permission: %s", permissions[i]);
- }
-
- return perms;
-}
-
-XdpPermissionFlags
-xdp_entry_get_permissions (FlatpakDbEntry *entry,
- const char *app_id)
-{
- g_autofree const char **permissions = NULL;
-
- if (strcmp (app_id, "") == 0)
- return XDP_PERMISSION_FLAGS_ALL;
-
- permissions = flatpak_db_entry_list_permissions (entry, app_id);
- return xdp_parse_permissions (permissions);
-}
-
-gboolean
-xdp_entry_has_permissions (FlatpakDbEntry *entry,
- const char *app_id,
- XdpPermissionFlags perms)
-{
- XdpPermissionFlags current_perms;
-
- current_perms = xdp_entry_get_permissions (entry, app_id);
-
- return (current_perms & perms) == perms;
-}
-
-char *
-xdp_name_from_id (guint32 doc_id)
-{
- return g_strdup_printf ("%x", doc_id);
-}
-
-const char *
-xdp_entry_get_path (FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) v = flatpak_db_entry_get_data (entry);
- g_autoptr(GVariant) c = g_variant_get_child_value (v, 0);
- return g_variant_get_bytestring (c);
-}
-
-char *
-xdp_entry_dup_basename (FlatpakDbEntry *entry)
-{
- const char *path = xdp_entry_get_path (entry);
-
- return g_path_get_basename (path);
-}
-
-char *
-xdp_entry_dup_dirname (FlatpakDbEntry *entry)
-{
- const char *path = xdp_entry_get_path (entry);
-
- return g_path_get_dirname (path);
-}
-
-guint64
-xdp_entry_get_device (FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) v = flatpak_db_entry_get_data (entry);
- g_autoptr(GVariant) c = g_variant_get_child_value (v, 1);
- return g_variant_get_uint64 (c);
-}
-
-guint64
-xdp_entry_get_inode (FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) v = flatpak_db_entry_get_data (entry);
- g_autoptr(GVariant) c = g_variant_get_child_value (v, 2);
- return g_variant_get_uint64 (c);
-}
-
-guint32
-xdp_entry_get_flags (FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) v = flatpak_db_entry_get_data (entry);
- g_autoptr(GVariant) c = g_variant_get_child_value (v, 3);
- return g_variant_get_uint32 (c);
-}
diff --git a/document-portal/xdp-util.h b/document-portal/xdp-util.h
deleted file mode 100644
index 007a2438..00000000
--- a/document-portal/xdp-util.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef XDP_UTIL_H
-#define XDP_UTIL_H
-
-#include <gio/gio.h>
-#include "flatpak-db.h"
-#include "xdp-enums.h"
-
-G_BEGIN_DECLS
-
-#define XDP_ENTRY_FLAG_UNIQUE (1 << 0)
-#define XDP_ENTRY_FLAG_TRANSIENT (1 << 1)
-
-const char ** xdg_unparse_permissions (XdpPermissionFlags permissions);
-XdpPermissionFlags xdp_parse_permissions (const char **permissions);
-
-XdpPermissionFlags xdp_entry_get_permissions (FlatpakDbEntry *entry,
- const char *app_id);
-gboolean xdp_entry_has_permissions (FlatpakDbEntry *entry,
- const char *app_id,
- XdpPermissionFlags perms);
-const char * xdp_entry_get_path (FlatpakDbEntry *entry);
-char * xdp_entry_dup_basename (FlatpakDbEntry *entry);
-char * xdp_entry_dup_dirname (FlatpakDbEntry *entry);
-guint64 xdp_entry_get_device (FlatpakDbEntry *entry);
-guint64 xdp_entry_get_inode (FlatpakDbEntry *entry);
-guint32 xdp_entry_get_flags (FlatpakDbEntry *entry);
-
-char * xdp_name_from_id (guint32 doc_id);
-
-
-G_END_DECLS
-
-#endif /* XDP_UTIL_H */
diff --git a/permission-store/Makefile.am.inc b/permission-store/Makefile.am.inc
deleted file mode 100644
index 023aad31..00000000
--- a/permission-store/Makefile.am.inc
+++ /dev/null
@@ -1,37 +0,0 @@
-libexec_PROGRAMS += \
- xdg-permission-store \
- $(NULL)
-
-service_in_files += permission-store/xdg-permission-store.service.in
-systemduserunit_DATA += permission-store/xdg-permission-store.service
-
-service_in_files += permission-store/org.freedesktop.impl.portal.PermissionStore.service.in
-dbus_service_DATA += permission-store/org.freedesktop.impl.portal.PermissionStore.service
-
-nodist_xdg_permission_store_SOURCES = permission-store/permission-store-dbus.c permission-store/permission-store-dbus.h
-BUILT_SOURCES += $(nodist_xdg_permission_store_SOURCES)
-CLEANFILES += $(nodist_xdg_permission_store_SOURCES)
-
-permission-store/permission-store-dbus.c: data/org.freedesktop.impl.portal.PermissionStore.xml Makefile
- mkdir -p $(builddir)/permission-store
- $(AM_V_GEN) $(GDBUS_CODEGEN) \
- --interface-prefix org.freedesktop.impl.portal. \
- --c-namespace Xdg \
- --generate-c-code $(builddir)/permission-store/permission-store-dbus \
- $(srcdir)/data/org.freedesktop.impl.portal.PermissionStore.xml \
- $(NULL)
-
-permission-store/%-dbus.h: permission-store/%-dbus.c
- @true # Built as a side-effect of the rules for the .c
-
-# also used by the document portal
-ps_dbus_built_sources = $(nodist_xdg_permission_store_SOURCES)
-
-xdg_permission_store_SOURCES = \
- permission-store/permission-store.c \
- permission-store/xdg-permission-store.c \
- permission-store/xdg-permission-store.h \
- $(NULL)
-
-xdg_permission_store_LDADD = $(AM_LDADD) $(BASE_LIBS) libflatpak-common.la
-xdg_permission_store_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) $(OSTREE_CFLAGS) $(GSYSTEM_CFLAGS) -I$(srcdir)/permission-store -I$(builddir)/permission-store
diff --git a/permission-store/org.freedesktop.impl.portal.PermissionStore.service.in b/permission-store/org.freedesktop.impl.portal.PermissionStore.service.in
deleted file mode 100644
index cb444f1d..00000000
--- a/permission-store/org.freedesktop.impl.portal.PermissionStore.service.in
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=org.freedesktop.impl.portal.PermissionStore
-Exec=@libexecdir@/xdg-permission-store
-SystemdService=xdg-permission-store.service
diff --git a/permission-store/permission-store.c b/permission-store/permission-store.c
deleted file mode 100644
index 30971af4..00000000
--- a/permission-store/permission-store.c
+++ /dev/null
@@ -1,146 +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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-
-#include <locale.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <gio/gio.h>
-#include "permission-store-dbus.h"
-#include "xdg-permission-store.h"
-#include "flatpak-utils.h"
-
-static void
-on_bus_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- xdg_permission_store_start (connection);
-}
-
-static void
-on_name_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
-}
-
-static void
-on_name_lost (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- exit (1);
-}
-
-static gboolean opt_verbose;
-static gboolean opt_replace;
-static gboolean opt_version;
-
-static GOptionEntry entries[] = {
- { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information", NULL },
- { "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace", NULL },
- { "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print version and exit", NULL },
- { NULL }
-};
-
-static void
-message_handler (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data)
-{
- /* Make this look like normal console output */
- if (log_level & G_LOG_LEVEL_DEBUG)
- printf ("XDP: %s\n", message);
- else
- printf ("%s: %s\n", g_get_prgname (), message);
-}
-
-static void
-printerr_handler (const gchar *string)
-{
- const char *prefix = "";
- const char *suffix = "";
- if (flatpak_fancy_output ())
- {
- prefix = FLATPAK_ANSI_RED FLATPAK_ANSI_BOLD_ON;
- suffix = FLATPAK_ANSI_BOLD_OFF FLATPAK_ANSI_COLOR_RESET;
- }
- fprintf (stderr, "%serror: %s%s\n", prefix, suffix, string);
-}
-
-int
-main (int argc,
- char **argv)
-{
- guint owner_id;
- GMainLoop *loop;
- GOptionContext *context;
- g_autoptr(GError) error = NULL;
-
- setlocale (LC_ALL, "");
-
- g_setenv ("GIO_USE_VFS", "local", TRUE);
-
- g_set_prgname (argv[0]);
-
- flatpak_migrate_from_xdg_app ();
-
- g_set_printerr_handler (printerr_handler);
-
- context = g_option_context_new ("- permission store");
- g_option_context_add_main_entries (context, entries, NULL);
- if (!g_option_context_parse (context, &argc, &argv, &error))
- {
- g_printerr ("Option parsing failed: %s", error->message);
- return 1;
- }
-
- if (opt_version)
- {
- g_print ("%s\n", PACKAGE_STRING);
- exit (EXIT_SUCCESS);
- }
-
- if (opt_verbose)
- g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL);
-
- g_set_prgname (argv[0]);
-
- owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
- "org.freedesktop.impl.portal.PermissionStore",
- G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
-
- on_bus_acquired,
- on_name_acquired,
- on_name_lost,
- NULL,
- NULL);
-
- loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (loop);
-
- g_bus_unown_name (owner_id);
-
- return 0;
-}
diff --git a/permission-store/xdg-permission-store.c b/permission-store/xdg-permission-store.c
deleted file mode 100644
index 499a35f1..00000000
--- a/permission-store/xdg-permission-store.c
+++ /dev/null
@@ -1,468 +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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-
-#include <locale.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gio/gio.h>
-#include "permission-store/permission-store-dbus.h"
-#include "xdg-permission-store.h"
-#include "flatpak-db.h"
-#include "flatpak-portal-error.h"
-
-GHashTable *tables = NULL;
-
-typedef struct
-{
- char *name;
- FlatpakDb *db;
- GList *outstanding_writes;
- GList *current_writes;
- gboolean writing;
-} Table;
-
-static void start_writeout (Table *table);
-
-static void
-table_free (Table *table)
-{
- g_free (table->name);
- g_object_unref (table->db);
- g_free (table);
-}
-
-static Table *
-lookup_table (const char *name,
- GDBusMethodInvocation *invocation)
-{
- Table *table;
- FlatpakDb *db;
- g_autofree char *dir = NULL;
- g_autofree char *path = NULL;
-
- g_autoptr(GError) error = NULL;
-
- table = g_hash_table_lookup (tables, name);
- if (table != NULL)
- return table;
-
- dir = g_build_filename (g_get_user_data_dir (), "flatpak/db", NULL);
- g_mkdir_with_parents (dir, 0755);
-
- path = g_build_filename (dir, name, NULL);
- db = flatpak_db_new (path, FALSE, &error);
- if (db == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_FAILED,
- "Unable to load db file: %s", error->message);
- return NULL;
- }
-
- table = g_new0 (Table, 1);
- table->name = g_strdup (name);
- table->db = db;
-
- g_hash_table_insert (tables, table->name, table);
-
- return table;
-}
-
-static void
-writeout_done (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- Table *table = user_data;
- GList *l;
-
- g_autoptr(GError) error = NULL;
- gboolean ok;
-
- ok = flatpak_db_save_content_finish (table->db, res, &error);
-
- for (l = table->current_writes; l != NULL; l = l->next)
- {
- GDBusMethodInvocation *invocation = l->data;
-
- if (ok)
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("()"));
- else
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_FAILED,
- "Unable to write db: %s", error->message);
- }
-
- g_list_free (table->current_writes);
- table->current_writes = NULL;
- table->writing = FALSE;
-
- if (table->outstanding_writes != NULL)
- start_writeout (table);
-}
-
-static void
-start_writeout (Table *table)
-{
- g_assert (table->current_writes == NULL);
- table->current_writes = table->outstanding_writes;
- table->outstanding_writes = NULL;
- table->writing = TRUE;
-
- flatpak_db_update (table->db);
-
- flatpak_db_save_content_async (table->db, NULL, writeout_done, table);
-}
-
-static void
-ensure_writeout (Table *table,
- GDBusMethodInvocation *invocation)
-{
- table->outstanding_writes = g_list_prepend (table->outstanding_writes, invocation);
-
- if (!table->writing)
- start_writeout (table);
-}
-
-static gboolean
-handle_list (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name)
-{
- Table *table;
-
- g_auto(GStrv) ids = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- ids = flatpak_db_list_ids (table->db);
-
- xdg_permission_store_complete_list (object, invocation, (const char * const *) ids);
-
- return TRUE;
-}
-
-static GVariant *
-get_app_permissions (FlatpakDbEntry *entry)
-{
- g_autofree const char **apps = NULL;
- GVariantBuilder builder;
- int i;
-
- apps = flatpak_db_entry_list_apps (entry);
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sas}"));
-
- for (i = 0; apps[i] != NULL; i++)
- {
- g_autofree const char **permissions = flatpak_db_entry_list_permissions (entry, apps[i]);
- g_variant_builder_add_value (&builder,
- g_variant_new ("{s@as}",
- apps[i],
- g_variant_new_strv (permissions, -1)));
- }
-
- return g_variant_ref_sink (g_variant_builder_end (&builder));
-}
-
-static gboolean
-handle_lookup (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name,
- const gchar *id)
-{
- Table *table;
-
- g_autoptr(GVariant) data = NULL;
- g_autoptr(GVariant) permissions = NULL;
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- entry = flatpak_db_lookup (table->db, id);
- if (entry == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "No entry for %s", id);
- return TRUE;
- }
-
- data = flatpak_db_entry_get_data (entry);
- permissions = get_app_permissions (entry);
-
- xdg_permission_store_complete_lookup (object, invocation,
- permissions,
- g_variant_new_variant (data));
-
- return TRUE;
-}
-
-static void
-emit_deleted (XdgPermissionStore *object,
- const gchar *table_name,
- const gchar *id,
- FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) data = NULL;
- g_autoptr(GVariant) permissions = NULL;
-
- data = flatpak_db_entry_get_data (entry);
- permissions = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sas}"), NULL, 0));
-
- xdg_permission_store_emit_changed (object,
- table_name, id,
- TRUE,
- g_variant_new_variant (data),
- permissions);
-}
-
-
-static void
-emit_changed (XdgPermissionStore *object,
- const gchar *table_name,
- const gchar *id,
- FlatpakDbEntry *entry)
-{
- g_autoptr(GVariant) data = NULL;
- g_autoptr(GVariant) permissions = NULL;
-
- data = flatpak_db_entry_get_data (entry);
- permissions = get_app_permissions (entry);
-
- xdg_permission_store_emit_changed (object,
- table_name, id,
- FALSE,
- g_variant_new_variant (data),
- permissions);
-}
-
-static gboolean
-handle_delete (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name,
- const gchar *id)
-{
- Table *table;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- entry = flatpak_db_lookup (table->db, id);
- if (entry == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "No entry for %s", id);
- return TRUE;
- }
-
- flatpak_db_set_entry (table->db, id, NULL);
- emit_deleted (object, table_name, id, entry);
-
- ensure_writeout (table, invocation);
-
- return TRUE;
-}
-
-static gboolean
-handle_set (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name,
- gboolean create,
- const gchar *id,
- GVariant *app_permissions,
- GVariant *data)
-{
- Table *table;
- GVariantIter iter;
- GVariant *child;
-
- g_autoptr(GVariant) data_child = NULL;
- g_autoptr(FlatpakDbEntry) old_entry = NULL;
- g_autoptr(FlatpakDbEntry) new_entry = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- old_entry = flatpak_db_lookup (table->db, id);
- if (old_entry == NULL && !create)
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "Id %s not found", id);
- return TRUE;
- }
-
- data_child = g_variant_get_child_value (data, 0);
- new_entry = flatpak_db_entry_new (data_child);
-
- /* Add all the given app permissions */
-
- g_variant_iter_init (&iter, app_permissions);
- while ((child = g_variant_iter_next_value (&iter)))
- {
- g_autoptr(FlatpakDbEntry) old_entry = NULL;
- const char *child_app_id;
- g_autofree const char **permissions;
-
- g_variant_get (child, "{&s^a&s}", &child_app_id, &permissions);
-
- old_entry = new_entry;
- new_entry = flatpak_db_entry_set_app_permissions (new_entry, child_app_id, (const char **) permissions);
-
- g_variant_unref (child);
- }
-
- flatpak_db_set_entry (table->db, id, new_entry);
- emit_changed (object, table_name, id, new_entry);
-
- ensure_writeout (table, invocation);
-
- return TRUE;
-}
-
-static gboolean
-handle_set_permission (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name,
- gboolean create,
- const gchar *id,
- const gchar *app,
- const gchar *const *permissions)
-{
- Table *table;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autoptr(FlatpakDbEntry) new_entry = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- entry = flatpak_db_lookup (table->db, id);
- if (entry == NULL)
- {
- if (create)
- {
- entry = flatpak_db_entry_new (NULL);
- }
- else
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "Id %s not found", id);
- return TRUE;
- }
- }
-
- new_entry = flatpak_db_entry_set_app_permissions (entry, app, (const char **) permissions);
- flatpak_db_set_entry (table->db, id, new_entry);
- emit_changed (object, table_name, id, new_entry);
-
- ensure_writeout (table, invocation);
-
- return TRUE;
-}
-
-static gboolean
-handle_set_value (XdgPermissionStore *object,
- GDBusMethodInvocation *invocation,
- const gchar *table_name,
- gboolean create,
- const gchar *id,
- GVariant *data)
-{
- Table *table;
-
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autoptr(FlatpakDbEntry) new_entry = NULL;
-
- table = lookup_table (table_name, invocation);
- if (table == NULL)
- return TRUE;
-
- entry = flatpak_db_lookup (table->db, id);
- if (entry == NULL)
- {
- if (create)
- {
- new_entry = flatpak_db_entry_new (data);
- }
- else
- {
- g_dbus_method_invocation_return_error (invocation,
- FLATPAK_PORTAL_ERROR, FLATPAK_PORTAL_ERROR_NOT_FOUND,
- "Id %s not found", id);
- return TRUE;
- }
- }
- else
- {
- new_entry = flatpak_db_entry_modify_data (entry, data);
- }
-
- flatpak_db_set_entry (table->db, id, new_entry);
- emit_changed (object, table_name, id, new_entry);
-
- ensure_writeout (table, invocation);
-
- return TRUE;
-}
-
-void
-xdg_permission_store_start (GDBusConnection *connection)
-{
- XdgPermissionStore *store;
- GError *error = NULL;
-
- tables = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) table_free);
-
- store = xdg_permission_store_skeleton_new ();
-
- xdg_permission_store_set_version (XDG_PERMISSION_STORE (store), 1);
-
- g_signal_connect (store, "handle-list", G_CALLBACK (handle_list), NULL);
- g_signal_connect (store, "handle-lookup", G_CALLBACK (handle_lookup), NULL);
- g_signal_connect (store, "handle-set", G_CALLBACK (handle_set), NULL);
- g_signal_connect (store, "handle-set-permission", G_CALLBACK (handle_set_permission), NULL);
- g_signal_connect (store, "handle-set-value", G_CALLBACK (handle_set_value), NULL);
- g_signal_connect (store, "handle-delete", G_CALLBACK (handle_delete), NULL);
-
- if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (store),
- connection,
- "/org/freedesktop/impl/portal/PermissionStore",
- &error))
- {
- g_warning ("error: %s", error->message);
- g_error_free (error);
- }
-}
diff --git a/permission-store/xdg-permission-store.h b/permission-store/xdg-permission-store.h
deleted file mode 100644
index 55dcc5c2..00000000
--- a/permission-store/xdg-permission-store.h
+++ /dev/null
@@ -1,28 +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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __FLATPAK_PERMISSION_STORE_H__
-#define __FLATPAK_PERMISSION_STORE_H__
-
-#include "flatpak-dbus.h"
-
-void xdg_permission_store_start (GDBusConnection *connection);
-
-#endif /* __FLATPAK_PERMISSION_STORE_H__ */
diff --git a/permission-store/xdg-permission-store.service.in b/permission-store/xdg-permission-store.service.in
deleted file mode 100644
index 66854306..00000000
--- a/permission-store/xdg-permission-store.service.in
+++ /dev/null
@@ -1,7 +0,0 @@
-[Unit]
-Description=sandboxed app permission store
-
-[Service]
-BusName=org.freedesktop.impl.portal.PermissionStore
-ExecStart=@libexecdir@/xdg-permission-store
-Type=dbus
diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc
index 2aef5d5a..e49e9ec8 100644
--- a/tests/Makefile.am.inc
+++ b/tests/Makefile.am.inc
@@ -12,27 +12,6 @@ else
AM_TESTS_ENVIRONMENT += FLATPAK_BWRAP=$$(cd $(top_builddir) && pwd)/flatpak-bwrap
endif
-testdb_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS)
-testdb_LDADD = \
- $(AM_LDADD) \
- $(BASE_LIBS) \
- $(OSTREE_LIBS) \
- libglnx.la \
- libflatpak-common.la \
- $(NULL)
-testdb_SOURCES = tests/testdb.c
-
-test_doc_portal_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS)
-test_doc_portal_LDADD = \
- $(AM_LDADD) \
- $(BASE_LIBS) \
- $(OSTREE_LIBS) \
- libglnx.la \
- libflatpak-common.la \
- $(NULL)
-test_doc_portal_SOURCES = tests/test-doc-portal.c
-nodist_test_doc_portal_SOURCES = $(xdp_dbus_built_sources)
-
testlibrary_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS)
testlibrary_LDADD = \
$(AM_LDADD) \
@@ -42,16 +21,6 @@ testlibrary_LDADD = \
$(NULL)
testlibrary_SOURCES = tests/testlibrary.c
-EXTRA_test_doc_portal_DEPENDENCIES = tests/services/org.freedesktop.impl.portal.PermissionStore.service tests/services/org.freedesktop.portal.Documents.service tests/services/org.freedesktop.Flatpak.service tests/services/org.freedesktop.Flatpak.SystemHelper.service
-
-tests/services/org.freedesktop.portal.Documents.service: document-portal/org.freedesktop.portal.Documents.service.in
- mkdir -p tests/services
- $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(abs_top_builddir)|" $< > $@
-
-tests/services/org.freedesktop.impl.portal.PermissionStore.service: permission-store/org.freedesktop.impl.portal.PermissionStore.service.in
- mkdir -p tests/services
- $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(abs_top_builddir)|" $< > $@
-
tests/services/org.freedesktop.Flatpak.service: session-helper/org.freedesktop.Flatpak.service.in
mkdir -p tests/services
$(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(abs_top_builddir)|" $< > $@
@@ -60,14 +29,12 @@ tests/services/org.freedesktop.Flatpak.SystemHelper.service: system-helper/org.f
mkdir -p tests/services
$(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(abs_top_builddir)|" -e "s|\@extraargs\@| --session --no-idle-exit|" $< > $@
-tests/libtest.sh: tests/services/org.freedesktop.impl.portal.PermissionStore.service tests/services/org.freedesktop.portal.Documents.service tests/services/org.freedesktop.Flatpak.service
+tests/libtest.sh: tests/services/org.freedesktop.Flatpak.service tests/services/org.freedesktop.Flatpak.SystemHelper.service
install-test-data-hook:
if ENABLE_INSTALLED_TESTS
mkdir -p $(DESTDIR)$(installed_testdir)/services
ln -sf $(dbus_servicedir)/org.freedesktop.Flatpak.service $(DESTDIR)$(installed_testdir)/services/
- ln -sf $(dbus_servicedir)/org.freedesktop.portal.Documents.service $(DESTDIR)$(installed_testdir)/services/
- ln -sf $(dbus_servicedir)/org.freedesktop.impl.portal.PermissionStore.service $(DESTDIR)$(installed_testdir)/services/
$(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@extraargs\@| --session --no-idle-exit|" $(top_srcdir)/system-helper/org.freedesktop.Flatpak.SystemHelper.service.in > $(DESTDIR)$(installed_testdir)/services/org.freedesktop.Flatpak.SystemHelper.service
endif
@@ -93,7 +60,6 @@ dist_installed_test_data = \
installed_test_keyringdir = $(installed_testdir)/test-keyring
installed_test_keyring2dir = $(installed_testdir)/test-keyring2
-installed_test_dbsdir = $(installed_testdir)/dbs
if ENABLE_INSTALLED_TESTS
dist_installed_test_keyring_DATA = \
@@ -106,7 +72,6 @@ dist_installed_test_keyring2_DATA = \
tests/test-keyring2/pubring.gpg \
tests/test-keyring2/secring.gpg \
$(NULL)
-dist_installed_test_dbs_DATA = tests/dbs/no_tables
endif
dist_test_scripts = \
@@ -127,15 +92,13 @@ dist_test_scripts = \
tests/test-update-remote-configuration.sh \
$(NULL)
-test_programs = testdb test-doc-portal testlibrary
+test_programs = testlibrary
@VALGRIND_CHECK_RULES@
VALGRIND_SUPPRESSIONS_FILES=tests/flatpak.supp tests/glib.supp
EXTRA_DIST += tests/flatpak.supp tests/glib.supp
DISTCLEANFILES += \
tests/services/org.freedesktop.Flatpak.service \
- tests/services/org.freedesktop.portal.Documents.service \
- tests/services/org.freedesktop.impl.portal.PermissionStore.service \
tests/services/org.freedesktop.Flatpak.SystemHelper.service \
tests/package_version.txt \
$(NULL)
diff --git a/tests/dbs/no_tables b/tests/dbs/no_tables
deleted file mode 100644
index c700bdb1..00000000
--- a/tests/dbs/no_tables
+++ /dev/null
Binary files differ
diff --git a/tests/test-doc-portal.c b/tests/test-doc-portal.c
deleted file mode 100644
index ff08316f..00000000
--- a/tests/test-doc-portal.c
+++ /dev/null
@@ -1,505 +0,0 @@
-#include "config.h"
-
-#include <locale.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "libglnx/libglnx.h"
-
-#include <gio/gio.h>
-#include <gio/gunixfdlist.h>
-
-#include "document-portal/xdp-dbus.h"
-
-#include "flatpak-dbus.h"
-
-char outdir[] = "/tmp/xdp-test-XXXXXX";
-
-GTestDBus *dbus;
-GDBusConnection *session_bus;
-XdpDbusDocuments *documents;
-char *mountpoint;
-static gboolean have_fuse;
-
-static char *
-make_doc_dir (const char *id, const char *app)
-{
- if (app)
- return g_build_filename (mountpoint, "by-app", app, id, NULL);
- else
- return g_build_filename (mountpoint, id, NULL);
-}
-
-static char *
-make_doc_path (const char *id, const char *basename, const char *app)
-{
- g_autofree char *dir = make_doc_dir (id, app);
-
- return g_build_filename (dir, basename, NULL);
-}
-
-static void
-assert_host_has_contents (const char *basename, const char *expected_contents)
-{
- g_autofree char *path = g_build_filename (outdir, basename, NULL);
- g_autofree char *real_contents = NULL;
- gsize real_contents_length;
- GError *error = NULL;
-
- g_file_get_contents (path, &real_contents, &real_contents_length, &error);
- g_assert_no_error (error);
- g_assert_cmpstr (real_contents, ==, expected_contents);
- g_assert_cmpuint (real_contents_length, ==, strlen (expected_contents));
-}
-
-static void
-assert_doc_has_contents (const char *id, const char *basename, const char *app, const char *expected_contents)
-{
- g_autofree char *path = make_doc_path (id, basename, app);
- g_autofree char *real_contents = NULL;
- gsize real_contents_length;
- GError *error = NULL;
-
- g_file_get_contents (path, &real_contents, &real_contents_length, &error);
- g_assert_no_error (error);
- g_assert_cmpstr (real_contents, ==, expected_contents);
- g_assert_cmpuint (real_contents_length, ==, strlen (expected_contents));
-}
-
-static void
-assert_doc_not_exist (const char *id, const char *basename, const char *app)
-{
- g_autofree char *path = make_doc_path (id, basename, app);
- struct stat buf;
- int res, fd;
-
- res = stat (path, &buf);
- g_assert_cmpint (res, ==, -1);
- g_assert_cmpint (errno, ==, ENOENT);
-
- fd = open (path, O_RDONLY);
- g_assert_cmpint (fd, ==, -1);
- g_assert_cmpint (errno, ==, ENOENT);
-}
-
-static char *
-export_file (const char *path, gboolean unique)
-{
- int fd, fd_id;
- GUnixFDList *fd_list = NULL;
-
- g_autoptr(GVariant) reply = NULL;
- GError *error = NULL;
- char *doc_id;
-
- fd = open (path, O_PATH | O_CLOEXEC);
- g_assert (fd >= 0);
-
- fd_list = g_unix_fd_list_new ();
- fd_id = g_unix_fd_list_append (fd_list, fd, &error);
- g_assert_no_error (error);
- close (fd);
-
- reply = g_dbus_connection_call_with_unix_fd_list_sync (session_bus,
- "org.freedesktop.portal.Documents",
- "/org/freedesktop/portal/documents",
- "org.freedesktop.portal.Documents",
- "Add",
- g_variant_new ("(hbb)", fd_id, !unique, FALSE),
- G_VARIANT_TYPE ("(s)"),
- G_DBUS_CALL_FLAGS_NONE,
- 30000,
- fd_list, NULL,
- NULL,
- &error);
- g_object_unref (fd_list);
- g_assert_no_error (error);
- g_assert (reply != NULL);
-
- g_variant_get (reply, "(s)", &doc_id);
- g_assert (doc_id != NULL);
- return doc_id;
-}
-
-static char *
-export_new_file (const char *basename, const char *contents, gboolean unique)
-{
- g_autofree char *path = NULL;
- GError *error = NULL;
-
- path = g_build_filename (outdir, basename, NULL);
-
- g_file_set_contents (path, contents, -1, &error);
- g_assert_no_error (error);
-
- return export_file (path, unique);
-}
-
-static gboolean
-update_doc (const char *id, const char *basename, const char *app, const char *contents, GError **error)
-{
- g_autofree char *path = make_doc_path (id, basename, app);
-
- return g_file_set_contents (path, contents, -1, error);
-}
-
-static gboolean
-update_from_host (const char *basename, const char *contents, GError **error)
-{
- g_autofree char *path = g_build_filename (outdir, basename, NULL);
-
- return g_file_set_contents (path, contents, -1, error);
-}
-
-
-static void
-grant_permissions (const char *id, const char *app, gboolean write)
-{
- g_autoptr(GPtrArray) permissions = g_ptr_array_new ();
- GError *error = NULL;
-
- g_ptr_array_add (permissions, "read");
- if (write)
- g_ptr_array_add (permissions, "write");
- g_ptr_array_add (permissions, NULL);
-
- xdp_dbus_documents_call_grant_permissions_sync (documents,
- id,
- app,
- (const char **) permissions->pdata,
- NULL,
- &error);
- g_assert_no_error (error);
-}
-
-static void
-test_create_doc (void)
-{
- g_autofree char *doc_path = NULL;
- g_autofree char *doc_app_path = NULL;
- g_autofree char *host_path = NULL;
- g_autofree char *id = NULL;
- g_autofree char *id2 = NULL;
- g_autofree char *id3 = NULL;
- g_autofree char *id4 = NULL;
- g_autofree char *id5 = NULL;
- const char *basename = "a-file";
- GError *error = NULL;
-
- if (!have_fuse)
- {
- g_test_skip ("this test requires FUSE");
- return;
- }
-
- /* Export a document */
- id = export_new_file (basename, "content", FALSE);
-
- /* Ensure its there and not viewable by apps */
- assert_doc_has_contents (id, basename, NULL, "content");
- assert_host_has_contents (basename, "content");
- assert_doc_not_exist (id, basename, "com.test.App1");
- assert_doc_not_exist (id, basename, "com.test.App2");
- assert_doc_not_exist (id, "another-file", NULL);
- assert_doc_not_exist ("anotherid", basename, NULL);
-
- /* Create a tmp file in same dir, ensure it works and can't be seen by other apps */
- assert_doc_not_exist (id, "tmp1", NULL);
- update_doc (id, "tmp1", NULL, "tmpdata1", &error);
- g_assert_no_error (error);
- assert_doc_has_contents (id, "tmp1", NULL, "tmpdata1");
- assert_doc_not_exist (id, "tmp1", "com.test.App1");
-
- /* Let App 1 see the document (but not write) */
- grant_permissions (id, "com.test.App1", FALSE);
-
- /* Ensure App 1 and only it can see the document and tmpfile */
- assert_doc_has_contents (id, basename, "com.test.App1", "content");
- assert_doc_not_exist (id, basename, "com.test.App2");
- assert_doc_not_exist (id, "tmp1", "com.test.App1");
-
- /* Make sure App 1 can't create a tmpfile */
- assert_doc_not_exist (id, "tmp2", "com.test.App1");
- update_doc (id, "tmp2", "com.test.App1", "tmpdata2", &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
- g_clear_error (&error);
- assert_doc_not_exist (id, "tmp2", "com.test.App1");
-
- /* Update the document contents, ensure this is propagater */
- update_doc (id, basename, NULL, "content2", &error);
- g_assert_no_error (error);
- assert_host_has_contents (basename, "content2");
- assert_doc_has_contents (id, basename, NULL, "content2");
- assert_doc_has_contents (id, basename, "com.test.App1", "content2");
- assert_doc_not_exist (id, basename, "com.test.App2");
- assert_doc_not_exist (id, "tmp1", "com.test.App2");
-
- /* Update the document contents outside fuse fd, ensure this is propagater */
- update_from_host (basename, "content3", &error);
- g_assert_no_error (error);
- assert_host_has_contents (basename, "content3");
- assert_doc_has_contents (id, basename, NULL, "content3");
- assert_doc_has_contents (id, basename, "com.test.App1", "content3");
- assert_doc_not_exist (id, basename, "com.test.App2");
- assert_doc_not_exist (id, "tmp1", "com.test.App2");
-
- /* Try to update the doc from an app that can't write to it */
- update_doc (id, basename, "com.test.App1", "content4", &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
- g_clear_error (&error);
-
- /* Try to create a tmp file for an app that is not allowed */
- assert_doc_not_exist (id, "tmp2", "com.test.App1");
- update_doc (id, "tmp2", "com.test.App1", "tmpdata2", &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
- g_clear_error (&error);
- assert_doc_not_exist (id, "tmp2", "com.test.App1");
- assert_doc_not_exist (id, "tmp2", NULL);
-
- /* Grant write permissions to App1 */
- grant_permissions (id, "com.test.App1", TRUE);
-
- /* update the doc from an app with write access */
- update_doc (id, basename, "com.test.App1", "content5", &error);
- g_assert_no_error (error);
- assert_host_has_contents (basename, "content5");
- assert_doc_has_contents (id, basename, NULL, "content5");
- assert_doc_has_contents (id, basename, "com.test.App1", "content5");
- assert_doc_not_exist (id, basename, "com.test.App2");
-
- /* Try to create a tmp file for an app */
- assert_doc_not_exist (id, "tmp3", "com.test.App1");
- update_doc (id, "tmp3", "com.test.App1", "tmpdata3", &error);
- g_assert_no_error (error);
- assert_doc_has_contents (id, "tmp3", "com.test.App1", "tmpdata3");
- assert_doc_not_exist (id, "tmp3", NULL);
-
- /* Re-Create a file from a fuse document file, in various ways */
- doc_path = make_doc_path (id, basename, NULL);
- doc_app_path = make_doc_path (id, basename, "com.test.App1");
- host_path = g_build_filename (outdir, basename, NULL);
- id2 = export_file (doc_path, FALSE);
- g_assert_cmpstr (id, ==, id2);
- id3 = export_file (doc_app_path, FALSE);
- g_assert_cmpstr (id, ==, id3);
- id4 = export_file (host_path, FALSE);
- g_assert_cmpstr (id, ==, id4);
-
- /* Ensure we can make a unique document */
- id5 = export_file (host_path, TRUE);
- g_assert_cmpstr (id, !=, id5);
-}
-
-static void
-test_recursive_doc (void)
-{
- g_autofree char *id = NULL;
- g_autofree char *id2 = NULL;
- g_autofree char *id3 = NULL;
- const char *basename = "recursive-file";
- g_autofree char *path = NULL;
- g_autofree char *app_path = NULL;
-
- if (!have_fuse)
- {
- g_test_skip ("this test requires FUSE");
- return;
- }
-
- id = export_new_file (basename, "recursive-content", FALSE);
-
- assert_doc_has_contents (id, basename, NULL, "recursive-content");
-
- path = make_doc_path (id, basename, NULL);
- g_print ("path: %s\n", path);
-
- id2 = export_file (path, FALSE);
-
- g_assert_cmpstr (id, ==, id2);
-
- grant_permissions (id, "com.test.App1", FALSE);
-
- app_path = make_doc_path (id, basename, "com.test.App1");
-
- id3 = export_file (app_path, FALSE);
-
- g_assert_cmpstr (id, ==, id3);
-}
-
-static void
-test_create_docs (void)
-{
- GError *error = NULL;
- g_autofree char *path1 = NULL;
- g_autofree char *path2 = NULL;
- int fd1, fd2;
- guint32 fd_ids[2];
- GUnixFDList *fd_list = NULL;
- gboolean res;
- char **out_doc_ids;
- g_autoptr(GVariant) out_extra = NULL;
- const char *permissions[] = { "read", NULL };
- const char *basenames[] = { "doc1", "doc2" };
- int i;
-
- if (!have_fuse)
- {
- g_test_skip ("this test requires FUSE");
- return;
- }
-
- path1 = g_build_filename (outdir, basenames[0], NULL);
- g_file_set_contents (path1, basenames[0], -1, &error);
- g_assert_no_error (error);
-
- fd1 = open (path1, O_PATH | O_CLOEXEC);
- g_assert (fd1 >= 0);
-
- path2 = g_build_filename (outdir, basenames[1], NULL);
- g_file_set_contents (path2, basenames[1], -1, &error);
- g_assert_no_error (error);
-
- fd2 = open (path2, O_PATH | O_CLOEXEC);
- g_assert (fd2 >= 0);
-
- fd_list = g_unix_fd_list_new ();
- fd_ids[0] = g_unix_fd_list_append (fd_list, fd1, &error);
- g_assert_no_error (error);
- close (fd1);
- fd_ids[1] = g_unix_fd_list_append (fd_list, fd2, &error);
- g_assert_no_error (error);
- close (fd2);
-
- res = xdp_dbus_documents_call_add_full_sync (documents,
- g_variant_new_fixed_array (G_VARIANT_TYPE_HANDLE,
- fd_ids, 2, sizeof (guint32)),
- 0,
- "org.other.App",
- permissions,
- fd_list,
- &out_doc_ids,
- &out_extra,
- NULL,
- NULL, &error);
- g_assert_no_error (error);
- g_assert (res);
-
- g_assert (g_strv_length (out_doc_ids) == 2);
- for (i = 0; i < 2; i++)
- {
- const char *id = out_doc_ids[i];
-
- /* Ensure its there and not viewable by apps */
- assert_doc_has_contents (id, basenames[i], NULL, basenames[i]);
- assert_host_has_contents (basenames[i], basenames[i]);
- assert_doc_not_exist (id, basenames[i], "com.test.App1");
- assert_doc_not_exist (id, basenames[i], "com.test.App2");
- assert_doc_not_exist (id, "another-file", NULL);
- assert_doc_not_exist ("anotherid", basenames[i], NULL);
-
- assert_doc_has_contents (id, basenames[i], "org.other.App", basenames[i]);
- update_doc (id, basenames[i], "org.other.App", "tmpdata2", &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
- g_clear_error (&error);
- }
- g_assert (g_variant_lookup_value (out_extra, "mountpoint", G_VARIANT_TYPE_VARIANT) == 0);
-}
-
-
-static void
-global_setup (void)
-{
- gboolean inited;
- g_autofree gchar *fusermount = NULL;
- GError *error = NULL;
- g_autofree gchar *services = NULL;
-
- fusermount = g_find_program_in_path ("fusermount");
- /* cache result so subsequent tests can be marked as skipped */
- have_fuse = (access ("/dev/fuse", W_OK) == 0 &&
- fusermount != NULL &&
- g_file_test (fusermount, G_FILE_TEST_IS_EXECUTABLE));
-
- if (!have_fuse)
- return;
-
- g_mkdtemp (outdir);
- g_print ("outdir: %s\n", outdir);
-
- g_setenv ("XDG_RUNTIME_DIR", outdir, TRUE);
- g_setenv ("XDG_DATA_HOME", outdir, TRUE);
-
- dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
- services = g_test_build_filename (G_TEST_BUILT, "services", NULL);
- g_test_dbus_add_service_dir (dbus, services);
- g_test_dbus_up (dbus);
-
- /* g_test_dbus_up unsets this, so re-set */
- g_setenv ("XDG_RUNTIME_DIR", outdir, TRUE);
-
- session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
- g_assert_no_error (error);
-
- documents = xdp_dbus_documents_proxy_new_sync (session_bus, 0,
- "org.freedesktop.portal.Documents",
- "/org/freedesktop/portal/documents",
- NULL, &error);
- g_assert_no_error (error);
- g_assert (documents != NULL);
-
- inited = xdp_dbus_documents_call_get_mount_point_sync (documents, &mountpoint,
- NULL, &error);
- g_assert_no_error (error);
- g_assert (inited);
- g_assert (mountpoint != NULL);
-}
-
-static void
-global_teardown (void)
-{
- GError *error = NULL;
-
- if (!have_fuse)
- return;
-
- g_free (mountpoint);
-
- g_object_unref (documents);
-
- g_dbus_connection_close_sync (session_bus, NULL, &error);
- g_assert_no_error (error);
-
- g_object_unref (session_bus);
-
- g_test_dbus_down (dbus);
-
- g_object_unref (dbus);
-
- /* We race on the unmount of the fuse fs, which causes the rm -rf to stop at the doc dir.
- This makes the chance of completely removing the directory higher */
- sleep (1);
-
- glnx_shutil_rm_rf_at (-1, outdir, NULL, NULL);
-}
-
-int
-main (int argc, char **argv)
-{
- int res;
-
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/db/create_doc", test_create_doc);
- g_test_add_func ("/db/recursive_doc", test_recursive_doc);
- g_test_add_func ("/db/create_docs", test_create_docs);
-
- global_setup ();
-
- res = g_test_run ();
-
- global_teardown ();
-
- return res;
-}
diff --git a/tests/testdb.c b/tests/testdb.c
deleted file mode 100644
index 92d2bd88..00000000
--- a/tests/testdb.c
+++ /dev/null
@@ -1,359 +0,0 @@
-#include "config.h"
-
-#include <glib.h>
-#include <flatpak-db.h>
-
-/*
-static void
-dump_db (FlatpakDb *db)
-{
- g_autofree char *s = flatpak_db_print (db);
- g_printerr ("\n%s\n", s);
-}
-*/
-
-static FlatpakDb *
-create_test_db (gboolean serialized)
-{
- FlatpakDb *db;
-
- g_autoptr(FlatpakDbEntry) entry1 = NULL;
- g_autoptr(FlatpakDbEntry) entry2 = NULL;
- g_autoptr(FlatpakDbEntry) entry3 = NULL;
- g_autoptr(FlatpakDbEntry) entry4 = NULL;
- g_autoptr(FlatpakDbEntry) entry5 = NULL;
- g_autoptr(FlatpakDbEntry) entry6 = NULL;
- g_autoptr(FlatpakDbEntry) entry7 = NULL;
- GError *error = NULL;
- const char *permissions1[] = { "read", "write", NULL };
- const char *permissions2[] = { "read", NULL };
- const char *permissions3[] = { "write", NULL };
-
- db = flatpak_db_new (NULL, FALSE, &error);
- g_assert_no_error (error);
- g_assert (db != NULL);
-
- {
- g_auto(GStrv) ids = flatpak_db_list_ids (db);
- g_assert (ids != NULL);
- g_assert (ids[0] == NULL);
- }
-
- {
- g_auto(GStrv) apps = flatpak_db_list_apps (db);
- g_assert (apps != NULL);
- g_assert (apps[0] == NULL);
- }
-
- entry1 = flatpak_db_entry_new (g_variant_new_string ("foo-data"));
- entry2 = flatpak_db_entry_set_app_permissions (entry1, "org.test.bapp", permissions2);
- entry3 = flatpak_db_entry_set_app_permissions (entry2, "org.test.app", permissions1);
- entry4 = flatpak_db_entry_set_app_permissions (entry3, "org.test.capp", permissions1);
-
- flatpak_db_set_entry (db, "foo", entry4);
-
- entry5 = flatpak_db_entry_new (g_variant_new_string ("bar-data"));
- entry6 = flatpak_db_entry_set_app_permissions (entry5, "org.test.app", permissions2);
- entry7 = flatpak_db_entry_set_app_permissions (entry6, "org.test.dapp", permissions3);
-
- flatpak_db_set_entry (db, "bar", entry7);
-
- if (serialized)
- flatpak_db_update (db);
-
- return db;
-}
-
-static void
-verify_test_db (FlatpakDb *db)
-{
- g_auto(GStrv) ids;
- g_autofree const char **apps1 = NULL;
- g_autofree const char **apps2 = NULL;
- g_auto(GStrv) all_apps = NULL;
-
- ids = flatpak_db_list_ids (db);
- g_assert (g_strv_length (ids) == 2);
- g_assert (g_strv_contains ((const char **) ids, "foo"));
- g_assert (g_strv_contains ((const char **) ids, "bar"));
-
- {
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autofree const char **permissions1 = NULL;
- g_autofree const char **permissions2 = NULL;
- g_autofree const char **permissions3 = NULL;
- g_autofree const char **permissions4 = NULL;
- g_autoptr(GVariant) data1 = NULL;
-
- entry = flatpak_db_lookup (db, "foo");
- g_assert (entry != NULL);
- data1 = flatpak_db_entry_get_data (entry);
- g_assert (data1 != NULL);
- g_assert_cmpstr (g_variant_get_type_string (data1), ==, "s");
- g_assert_cmpstr (g_variant_get_string (data1, NULL), ==, "foo-data");
- apps1 = flatpak_db_entry_list_apps (entry);
- g_assert (g_strv_length ((char **) apps1) == 3);
- g_assert (g_strv_contains (apps1, "org.test.app"));
- g_assert (g_strv_contains (apps1, "org.test.bapp"));
- g_assert (g_strv_contains (apps1, "org.test.capp"));
- permissions1 = flatpak_db_entry_list_permissions (entry, "org.test.app");
- g_assert (g_strv_length ((char **) permissions1) == 2);
- g_assert (g_strv_contains (permissions1, "read"));
- g_assert (g_strv_contains (permissions1, "write"));
- permissions2 = flatpak_db_entry_list_permissions (entry, "org.test.bapp");
- g_assert (g_strv_length ((char **) permissions2) == 1);
- g_assert (g_strv_contains (permissions2, "read"));
- permissions3 = flatpak_db_entry_list_permissions (entry, "org.test.capp");
- g_assert (g_strv_length ((char **) permissions3) == 2);
- g_assert (g_strv_contains (permissions3, "read"));
- g_assert (g_strv_contains (permissions3, "write"));
- permissions4 = flatpak_db_entry_list_permissions (entry, "org.test.noapp");
- g_assert (permissions4 != NULL);
- g_assert (g_strv_length ((char **) permissions4) == 0);
- }
-
- {
- g_autoptr(FlatpakDbEntry) entry = NULL;
- g_autofree const char **permissions5 = NULL;
- g_autofree const char **permissions6 = NULL;
- g_autoptr(GVariant) data2 = NULL;
-
- entry = flatpak_db_lookup (db, "bar");
- g_assert (entry != NULL);
- data2 = flatpak_db_entry_get_data (entry);
- g_assert (data2 != NULL);
- g_assert_cmpstr (g_variant_get_type_string (data2), ==, "s");
- g_assert_cmpstr (g_variant_get_string (data2, NULL), ==, "bar-data");
- apps2 = flatpak_db_entry_list_apps (entry);
- g_assert (g_strv_length ((char **) apps2) == 2);
- g_assert (g_strv_contains (apps2, "org.test.app"));
- g_assert (g_strv_contains (apps2, "org.test.dapp"));
- permissions5 = flatpak_db_entry_list_permissions (entry, "org.test.app");
- g_assert (g_strv_length ((char **) permissions5) == 1);
- g_assert (g_strv_contains (permissions5, "read"));
- permissions6 = flatpak_db_entry_list_permissions (entry, "org.test.dapp");
- g_assert (g_strv_length ((char **) permissions6) == 1);
- g_assert (g_strv_contains (permissions6, "write"));
- }
-
- {
- g_autoptr(FlatpakDbEntry) entry = NULL;
- entry = flatpak_db_lookup (db, "gazonk");
- g_assert (entry == NULL);
- }
-
- all_apps = flatpak_db_list_apps (db);
- g_assert (g_strv_length (all_apps) == 4);
- g_assert (g_strv_contains ((const char **) all_apps, "org.test.app"));
- g_assert (g_strv_contains ((const char **) all_apps, "org.test.bapp"));
- g_assert (g_strv_contains ((const char **) all_apps, "org.test.capp"));
- g_assert (g_strv_contains ((const char **) all_apps, "org.test.dapp"));
-}
-
-static void
-test_db_open (void)
-{
- GError *error = NULL;
- FlatpakDb *db;
-
- db = flatpak_db_new (g_test_get_filename (G_TEST_DIST, "dbs", "does_not_exist", NULL), TRUE, &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
- g_assert (db == NULL);
- g_clear_error (&error);
-
- db = flatpak_db_new (g_test_get_filename (G_TEST_DIST, "dbs", "does_not_exist", NULL), FALSE, &error);
- g_assert_no_error (error);
- g_assert (db != NULL);
- g_clear_error (&error);
- g_object_unref (db);
-
- db = flatpak_db_new (g_test_get_filename (G_TEST_DIST, "dbs", "no_tables", NULL), TRUE, &error);
- g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
- g_assert (db == NULL);
- g_clear_error (&error);
-}
-
-static void
-test_serialize (void)
-{
- g_autoptr(FlatpakDb) db = NULL;
- g_autoptr(FlatpakDb) db2 = NULL;
- g_autofree char *dump1 = NULL;
- g_autofree char *dump2 = NULL;
- g_autofree char *dump3 = NULL;
- GError *error = NULL;
- char tmpfile[] = "/tmp/testdbXXXXXX";
- int fd;
-
- db = create_test_db (FALSE);
-
- verify_test_db (db);
-
- dump1 = flatpak_db_print (db);
-
- g_assert (flatpak_db_is_dirty (db));
-
- flatpak_db_update (db);
-
- verify_test_db (db);
-
- g_assert (!flatpak_db_is_dirty (db));
-
- dump2 = flatpak_db_print (db);
-
- g_assert_cmpstr (dump1, ==, dump2);
-
- fd = g_mkstemp (tmpfile);
- close (fd);
-
- flatpak_db_set_path (db, tmpfile);
-
- flatpak_db_save_content (db, &error);
- g_assert_no_error (error);
-
- db2 = flatpak_db_new (tmpfile, TRUE, &error);
- g_assert_no_error (error);
- g_assert (db2 != NULL);
-
- dump3 = flatpak_db_print (db2);
-
- g_assert_cmpstr (dump1, ==, dump3);
-
- unlink (tmpfile);
-}
-
-static void
-test_modify (void)
-{
- g_autoptr(FlatpakDb) db = NULL;
- const char *permissions[] = { "read", "write", "execute", NULL };
- const char *no_permissions[] = { NULL };
-
- db = create_test_db (FALSE);
-
- /* Add permission */
- {
- g_autoptr(FlatpakDbEntry) entry1 = NULL;
- g_autoptr(FlatpakDbEntry) entry2 = NULL;
-
- entry1 = flatpak_db_lookup (db, "foo");
- entry2 = flatpak_db_entry_set_app_permissions (entry1, "org.test.app", permissions);
- flatpak_db_set_entry (db, "foo", entry2);
- }
-
- /* Add entry */
- {
- g_autoptr(FlatpakDbEntry) entry1 = NULL;
- g_autoptr(FlatpakDbEntry) entry2 = NULL;
-
- entry1 = flatpak_db_entry_new (g_variant_new_string ("gazonk-data"));
- entry2 = flatpak_db_entry_set_app_permissions (entry1, "org.test.eapp", permissions);
- flatpak_db_set_entry (db, "gazonk", entry2);
- }
-
- /* Remove permission */
- {
- g_autoptr(FlatpakDbEntry) entry1 = NULL;
- g_autoptr(FlatpakDbEntry) entry2 = NULL;
-
- entry1 = flatpak_db_lookup (db, "bar");
- entry2 = flatpak_db_entry_set_app_permissions (entry1, "org.test.dapp", no_permissions);
- flatpak_db_set_entry (db, "bar", entry2);
- }
-
- /* Verify */
- {
- g_autoptr(FlatpakDbEntry) entry5 = NULL;
- g_autoptr(FlatpakDbEntry) entry6 = NULL;
- g_autoptr(FlatpakDbEntry) entry7 = NULL;
- g_autofree const char **apps2 = NULL;
- g_auto(GStrv) apps3 = NULL;
- g_autofree const char **permissions1 = NULL;
- g_autofree const char **permissions2 = NULL;
- g_autofree const char **permissions3 = NULL;
-
- entry5 = flatpak_db_lookup (db, "foo");
- permissions1 = flatpak_db_entry_list_permissions (entry5, "org.test.app");
- g_assert (g_strv_length ((char **) permissions1) == 3);
- g_assert (g_strv_contains (permissions1, "read"));
- g_assert (g_strv_contains (permissions1, "write"));
- g_assert (g_strv_contains (permissions1, "execute"));
-
- entry6 = flatpak_db_lookup (db, "bar");
- permissions2 = flatpak_db_entry_list_permissions (entry6, "org.test.dapp");
- g_assert (g_strv_length ((char **) permissions2) == 0);
-
- entry7 = flatpak_db_lookup (db, "gazonk");
- permissions3 = flatpak_db_entry_list_permissions (entry7, "org.test.eapp");
- g_assert (g_strv_length ((char **) permissions3) == 3);
- g_assert (g_strv_contains (permissions3, "read"));
- g_assert (g_strv_contains (permissions3, "write"));
- g_assert (g_strv_contains (permissions3, "execute"));
-
- apps2 = flatpak_db_entry_list_apps (entry6);
- g_assert_cmpint (g_strv_length ((char **) apps2), ==, 1);
- g_assert (g_strv_contains (apps2, "org.test.app"));
-
- apps3 = flatpak_db_list_apps (db);
- g_assert_cmpint (g_strv_length (apps3), ==, 4);
- g_assert (g_strv_contains ((const char **) apps3, "org.test.app"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.bapp"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.capp"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.eapp"));
- }
-
- flatpak_db_update (db);
-
- /* Verify after serialize */
- {
- g_autoptr(FlatpakDbEntry) entry5 = NULL;
- g_autoptr(FlatpakDbEntry) entry6 = NULL;
- g_autoptr(FlatpakDbEntry) entry7 = NULL;
- g_autofree const char **apps2 = NULL;
- g_auto(GStrv) apps3 = NULL;
- g_autofree const char **permissions1 = NULL;
- g_autofree const char **permissions2 = NULL;
- g_autofree const char **permissions3 = NULL;
-
- entry5 = flatpak_db_lookup (db, "foo");
- permissions1 = flatpak_db_entry_list_permissions (entry5, "org.test.app");
- g_assert (g_strv_length ((char **) permissions1) == 3);
- g_assert (g_strv_contains (permissions1, "read"));
- g_assert (g_strv_contains (permissions1, "write"));
- g_assert (g_strv_contains (permissions1, "execute"));
-
- entry6 = flatpak_db_lookup (db, "bar");
- permissions2 = flatpak_db_entry_list_permissions (entry6, "org.test.dapp");
- g_assert (g_strv_length ((char **) permissions2) == 0);
-
- entry7 = flatpak_db_lookup (db, "gazonk");
- permissions3 = flatpak_db_entry_list_permissions (entry7, "org.test.eapp");
- g_assert (g_strv_length ((char **) permissions3) == 3);
- g_assert (g_strv_contains (permissions3, "read"));
- g_assert (g_strv_contains (permissions3, "write"));
- g_assert (g_strv_contains (permissions3, "execute"));
-
- apps2 = flatpak_db_entry_list_apps (entry6);
- g_assert_cmpint (g_strv_length ((char **) apps2), ==, 1);
- g_assert (g_strv_contains (apps2, "org.test.app"));
-
- apps3 = flatpak_db_list_apps (db);
- g_assert_cmpint (g_strv_length (apps3), ==, 4);
- g_assert (g_strv_contains ((const char **) apps3, "org.test.app"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.bapp"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.capp"));
- g_assert (g_strv_contains ((const char **) apps3, "org.test.eapp"));
- }
-}
-
-int
-main (int argc, char **argv)
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/db/open", test_db_open);
- g_test_add_func ("/db/serialize", test_serialize);
- g_test_add_func ("/db/modify", test_modify);
-
- return g_test_run ();
-}