summaryrefslogtreecommitdiff
path: root/metadata/metatree.c
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2015-03-10 12:54:39 +0100
committerOndrej Holy <oholy@redhat.com>2015-03-11 10:48:33 +0100
commitf7f18bb6e7576672c2240c8ead8dfa4a2668d478 (patch)
tree1a1f770ead7d8d40a35e8e88f8f14d4e303feb0e /metadata/metatree.c
parenta4f0bf37825378af9042eb6d95aa0d3d2b9df8d4 (diff)
downloadgvfs-f7f18bb6e7576672c2240c8ead8dfa4a2668d478.tar.gz
metadata: don't crash if tree write out failed
meta_tree_init can fail after we failed to write out an updated tree. Backup corrupted file and start with empty tree to avoid consequent crashes. https://bugzilla.gnome.org/show_bug.cgi?id=598561
Diffstat (limited to 'metadata/metatree.c')
-rw-r--r--metadata/metatree.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/metadata/metatree.c b/metadata/metatree.c
index 4c6d5f00..4964c682 100644
--- a/metadata/metatree.c
+++ b/metadata/metatree.c
@@ -643,6 +643,7 @@ meta_tree_refresh_locked (MetaTree *tree, gboolean force_reread)
return TRUE;
}
+/* NB: The tree is uninitialized if FALSE is returned! */
gboolean
meta_tree_refresh (MetaTree *tree)
{
@@ -2339,7 +2340,16 @@ meta_tree_flush_locked (MetaTree *tree)
builder = meta_builder_new ();
- copy_tree_to_builder (tree, tree->root, builder->root);
+ if (tree->root)
+ {
+ copy_tree_to_builder (tree, tree->root, builder->root);
+ }
+ else
+ {
+ /* It shouldn't happen, because tree is recovered in case of failed write
+ * out. Skip copy_tree_to_builder to avoid crash. */
+ g_warning ("meta_tree_flush_locked: tree->root == NULL, possible data loss");
+ }
if (tree->journal)
apply_journal_to_builder (tree, builder);
@@ -2347,14 +2357,44 @@ meta_tree_flush_locked (MetaTree *tree)
res = meta_builder_write (builder,
meta_tree_get_filename (tree));
if (res)
- /* Force re-read since we wrote a new file */
- res = meta_tree_refresh_locked (tree, TRUE);
+ {
+ /* Force re-read since we wrote a new file */
+ res = meta_tree_refresh_locked (tree, TRUE);
+
+ if (tree->root == NULL)
+ {
+ /* It shouldn't happen. We failed to write out an updated tree
+ * probably, therefore all the data are lost. Backup the file and
+ * reload the tree to avoid further crashes. */
+ GTimeVal tv;
+ char *timestamp, *backup;
+
+ g_get_current_time (&tv);
+ timestamp = g_time_val_to_iso8601 (&tv);
+ backup = g_strconcat (meta_tree_get_filename (tree), ".backup.",
+ timestamp, NULL);
+ g_rename (meta_tree_get_filename (tree), backup);
+
+ g_warning ("meta_tree_flush_locked: tree->root == NULL, possible data loss\n"
+ "corrupted file was moved to: %s\n"
+ "(please make a comment on https://bugzilla.gnome.org/show_bug.cgi?id=598561 "
+ "and attach the corrupted file)",
+ backup);
+
+ g_free (timestamp);
+ g_free (backup);
+
+ res = meta_tree_refresh_locked (tree, TRUE);
+ g_assert (res);
+ }
+ }
meta_builder_free (builder);
return res;
}
+/* NB: The tree can be uninitialized if FALSE is returned! */
gboolean
meta_tree_flush (MetaTree *tree)
{