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 b03bc44c5..3ee3dcd0d 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 b6e9eb80d..37c00fc58 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 f0909fec2..adf77a202 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 79300c888..861428d78 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 d6a56e7df..d3c299b88 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 046a46225..5ef7f8f31 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"; };