From 9d455dd943025e7551e5ec4aa7e153f46cfb4af7 Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Fri, 19 Feb 2016 18:34:16 +0000 Subject: [PATCH 1/2] Check if we can write to files, instead of checking if we are root In theory this lets us operate without being root, although with apt we still have hardcoded paths. --- src/as-cache-builder.c | 22 +++++++++++++++++++--- src/as-cache-builder.h | 1 + src/as-utils-private.h | 2 ++ src/as-utils.c | 28 ++++++++++++++++++++++++++++ tools/ascli-mdata-actions.c | 15 +++++++-------- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/as-cache-builder.c b/src/as-cache-builder.c index b03bc44c..3ee3dcd0 100644 --- a/src/as-cache-builder.c +++ b/src/as-cache-builder.c @@ -149,7 +149,9 @@ as_cache_builder_setup (AsCacheBuilder *builder, const gchar *dbpath) as_cache_builder_check_cache_ctime (builder); /* try to create db directory, in case it doesn't exist */ - g_mkdir_with_parents (priv->db_path, 0755); + if (g_mkdir_with_parents (priv->db_path, 0755) < 0 || + !as_utils_is_writable (priv->db_path)) + return FALSE; ret = xa_database_write_initialize (priv->db_w, priv->db_path); return ret; @@ -293,9 +295,15 @@ as_cache_builder_scan_apt (AsCacheBuilder *builder, gboolean force, GError **err guint i; AsCacheBuilderPrivate *priv = GET_PRIVATE (builder); - /* we can't do anything here if we're not root */ - if (!as_utils_is_root ()) + /* we can't do anything here if we can't write to the target directories */ + if (!as_utils_is_writable (appstream_yml_target) || !as_utils_is_writable (appstream_icons_target)) + { + g_set_error (error, + AS_CACHE_BUILDER_ERROR, + AS_CACHE_BUILDER_ERROR_UNWRITABLE_DEST, + _("Cannot write to destination directory.")); return; + } /* skip this step if the APT lists directory doesn't exist */ if (!g_file_test (apt_lists_dir, G_FILE_TEST_IS_DIR)) { @@ -441,6 +449,14 @@ as_cache_builder_refresh (AsCacheBuilder *builder, gboolean force, GError **erro if (tmp_error != NULL) { /* the exact error is not forwarded here, since we might be able to partially update the cache */ g_warning ("Error while collecting metadata: %s", tmp_error->message); + if (g_error_matches (tmp_error, + AS_CACHE_BUILDER_ERROR, + AS_CACHE_BUILDER_ERROR_UNWRITABLE_DEST)) + { + GError *err = g_error_copy (tmp_error); + *error = err; + return FALSE; + } g_error_free (tmp_error); tmp_error = NULL; } diff --git a/src/as-cache-builder.h b/src/as-cache-builder.h index b6e9eb80..37c00fc5 100644 --- a/src/as-cache-builder.h +++ b/src/as-cache-builder.h @@ -56,6 +56,7 @@ GQuark as_cache_builder_error_quark (void); typedef enum { AS_CACHE_BUILDER_ERROR_FAILED, AS_CACHE_BUILDER_ERROR_PARTIALLY_FAILED, + AS_CACHE_BUILDER_ERROR_UNWRITABLE_DEST, /*< private >*/ AS_CACHE_BUILDER_ERROR_LAST } AsCacheBuilderError; diff --git a/src/as-utils-private.h b/src/as-utils-private.h index f0909fec..adf77a20 100644 --- a/src/as-utils-private.h +++ b/src/as-utils-private.h @@ -42,6 +42,8 @@ GPtrArray *as_utils_find_files (const gchar *dir, gboolean as_utils_is_root (void); +gboolean as_utils_is_writable (const gchar *path); + gchar *as_str_replace (const gchar *str, const gchar *old_str, const gchar *new_str); diff --git a/src/as-utils.c b/src/as-utils.c index 79300c88..861428d7 100644 --- a/src/as-utils.c +++ b/src/as-utils.c @@ -419,6 +419,34 @@ as_utils_is_root (void) return (vuid == ((uid_t) 0)); } +/** + * as_utils_is_writable: + * @path: the path to check. + * + * Checks if a path is writable. + */ +gboolean +as_utils_is_writable (const gchar *path) +{ + g_autoptr(GFile) file; + g_autoptr(GFileInfo) file_info; + + file = g_file_new_for_path (path); + + file_info = g_file_query_info ( + file, + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + + if (file_info && g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) + return g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); + + return FALSE; +} + + /** * as_get_current_locale: * diff --git a/tools/ascli-mdata-actions.c b/tools/ascli-mdata-actions.c index d6a56e7d..d3c299b8 100644 --- a/tools/ascli-mdata-actions.c +++ b/tools/ascli-mdata-actions.c @@ -25,6 +25,7 @@ #include #include "ascli-utils.h" #include "as-cache-builder.h" +#include "as-settings-private.h" /** * ascli_refresh_cache: @@ -36,13 +37,6 @@ ascli_refresh_cache (const gchar *dbpath, const gchar *datapath, gboolean forced g_autoptr(GError) error = NULL; gboolean ret; - if (dbpath == NULL) { - if (getuid () != ((uid_t) 0)) { - g_print ("%s\n", _("You need to run this command with superuser permissions!")); - return 2; - } - } - cbuilder = as_cache_builder_new (); if (datapath != NULL) { @@ -54,7 +48,12 @@ ascli_refresh_cache (const gchar *dbpath, const gchar *datapath, gboolean forced g_strfreev (strv); } - as_cache_builder_setup (cbuilder, dbpath); + ret = as_cache_builder_setup (cbuilder, dbpath); + if (!ret) + { + g_printerr ("Can't write to %s\n", dbpath ? dbpath : AS_APPSTREAM_CACHE_PATH); + return 2; + } ret = as_cache_builder_refresh (cbuilder, forced, &error); if (ret) { From d498c6c62ae90bb993f1eea2a30c77a2778a5415 Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Fri, 19 Feb 2016 18:36:08 +0000 Subject: [PATCH 2/2] 50appstream: Don't run if we can't write to the system paths --- contrib/apt-conf/50appstream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/apt-conf/50appstream b/contrib/apt-conf/50appstream index 046a4622..5ef7f8f3 100644 --- a/contrib/apt-conf/50appstream +++ b/contrib/apt-conf/50appstream @@ -44,5 +44,5 @@ Acquire::IndexTargets { # Refresh AppStream cache when APT's cache is updated (i.e. apt-cache update) APT::Update::Post-Invoke-Success { - "if /usr/bin/test -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi"; + "if /usr/bin/test -w /var/cache/app-info -a -w /var/lib/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi"; };