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"; }; 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) {