filters: Make a backup copy of the filter when it is set and use when needed

We still look at the regular file to pick up changes, but to avoid
issues if the file disappears (for example if it was in a package
that was uninstalled) then we still have something to show so we don't
start accidentally showing unfiltered stuff.

Closes: #2890
Approved by: alexlarsson
This commit is contained in:
Alexander Larsson 2019-05-08 15:05:20 +02:00 committed by Atomic Bot
parent 02bf8e32e1
commit d7bc26031c
2 changed files with 66 additions and 2 deletions

View File

@ -10302,6 +10302,7 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self,
{
RemoteFilter *filter = NULL;
const char *filter_path;
gboolean handled_fallback = FALSE;
g_autoptr(GFile) filter_file = NULL;
if (checksum_out)
@ -10331,6 +10332,15 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self,
filter = NULL; /* New path, reload */
else if ((now - filter->last_mtime_check) > (1000 * (FILTER_MTIME_CHECK_TIMEOUT_MSEC)))
{
/* Fall back to backup copy if remote filter disappears */
handled_fallback = TRUE;
if (!g_file_query_exists (filter_file, NULL))
{
char *basename = g_strconcat (name, ".filter", NULL);
g_object_unref (filter_file);
filter_file = flatpak_build_file (self->basedir, "repo", basename, NULL);
}
filter->last_mtime_check = now;
if (!get_mtime (filter_file, &mtime, NULL, NULL) ||
mtime.tv_sec != filter->mtime.tv_sec ||
@ -10354,6 +10364,14 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self,
if (filter) /* This is outside the lock, but we already copied the returned data, and we're not dereferencing filter */
return TRUE;
/* Fall back to backup copy if remote filter disappears */
if (!handled_fallback && !g_file_query_exists (filter_file, NULL))
{
char *basename = g_strconcat (name, ".filter", NULL);
g_object_unref (filter_file);
filter_file = flatpak_build_file (self->basedir, "repo", basename, NULL);
}
filter = remote_filter_load (filter_file, error);
if (filter == NULL)
return FALSE;
@ -12741,6 +12759,7 @@ flatpak_dir_modify_remote (FlatpakDir *self,
g_autofree char *url = NULL;
g_autofree char *metalink = NULL;
g_autoptr(GKeyFile) new_config = NULL;
g_autofree gchar *filter_path = NULL;
gboolean has_remote;
if (strchr (remote_name, '/') != NULL)
@ -12819,6 +12838,32 @@ flatpak_dir_modify_remote (FlatpakDir *self,
imported, (imported == 1) ? "" : "s", remote_name);
}
filter_path = g_key_file_get_value (new_config, group, "xa.filter", NULL);
if (filter_path && *filter_path && g_file_test (filter_path, G_FILE_TEST_EXISTS))
{
/* Make a backup filter copy in case it goes away later */
char *filter_name = g_strconcat (remote_name, ".filter", NULL);
g_autoptr(GFile) filter_file = g_file_new_for_path (filter_path);
g_autoptr(GFile) filter_copy = flatpak_build_file (self->basedir, "repo", filter_name, NULL);
g_autoptr(GError) local_error = NULL;
g_autofree char *backup_data = NULL;
gsize backup_data_size;
if (g_file_load_contents (filter_file, cancellable, &backup_data, &backup_data_size, NULL, &local_error))
{
g_autofree char *backup_data_copy =
g_strdup_printf ("# backup copy of %s, do not edit!\n%s", filter_path, backup_data);
if (!g_file_replace_contents (filter_copy, backup_data_copy, strlen (backup_data_copy),
NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, cancellable, &local_error))
g_debug ("Failed to save backup copy of filter file %s: %s\n", filter_path, local_error->message);
}
else
{
g_debug ("Failed to read filter %s file while making a backup copy: %s\n", filter_path, local_error->message);
}
}
if (!flatpak_dir_mark_changed (self, error))
return FALSE;

View File

@ -620,8 +620,9 @@ assert_file_has_content remote-ref-info "ID: org\.test\.Hello"
${FLATPAK} ${U} update --appstream test-repo
assert_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello"
${FLATPAK} ${U} remote-modify test-repo --filter ${test_builddir}/test.filter
# Make a copy so we can remove it later
cp ${test_builddir}/test.filter test.filter
${FLATPAK} ${U} remote-modify test-repo --filter $(pwd)/test.filter
${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log
@ -640,6 +641,24 @@ fi
${FLATPAK} ${U} update --appstream test-repo
assert_not_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello"
# Ensure that filter works even when the filter file is removed (uses the backup)
rm test.filter
${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log
assert_not_file_has_content remote-ls-log "app/org\.test\.Hello"
assert_not_file_has_content remote-ls-log "runtime/org\.test\.Hello\.Locale"
assert_file_has_content remote-ls-log "runtime/org\.test\.Platform"
if ${FLATPAK} ${U} remote-info test-repo org.test.Hello > remote-ref-info; then
assert_not_reached "flatpak remote-info test-repo org.test.Hello should fail due to filter"
fi
if ${FLATPAK} ${U} install -y test-repo org.test.Hello; then
assert_not_reached "should not be able to install org.test.Hello should fail due to filter"
fi
${FLATPAK} ${U} update --appstream test-repo
assert_not_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello"
# Remove filter
${FLATPAK} ${U} remote-modify test-repo --no-filter
${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log