[easytag] Fix Ogg tag writing on Windows



commit 2576fbaf7edbfdb60d25692c7c3407f36751fe68
Author: David King <amigadave amigadave com>
Date:   Wed Nov 9 16:22:37 2016 +0000

    Fix Ogg tag writing on Windows
    
    Under Windows, if a file is opened for reading, it cannot be opened a
    second time for writing. The Vorbis comment code keeps the file open
    for reading throughout the process of writing new tags, mostly because
    the audio stream must be read into memory before being written out
    after the new tags. Avoid the problem by closing the input stream only
    during the writing process, and at all other times maintaining a
    consistent state, with the input stream open.
    
    https://mail.gnome.org/archives/easytag-list/2016-November/msg00000.html

 src/tags/vcedit.c |   47 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 43 insertions(+), 4 deletions(-)
---
diff --git a/src/tags/vcedit.c b/src/tags/vcedit.c
index 536170b..cf43428 100644
--- a/src/tags/vcedit.c
+++ b/src/tags/vcedit.c
@@ -1045,19 +1045,58 @@ cleanup:
     buf = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (ostream));
     size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (ostream));
 
+    /* At least on Windows, writing to a file with an open-for-reading stream
+     * fails, so close the input stream before writing to the file. */
+    if (!g_input_stream_close (G_INPUT_STREAM (state->in), NULL, error))
+    {
+        /* Ignore the _close() failure, and try the write anyway. */
+        g_warning ("Error closing Ogg file for reading: %s",
+                   (*error)->message);
+        g_clear_error (error);
+    }
+
+    g_object_unref (state->in);
+    state->in = NULL;
+
     /* Write the in-memory data back out to the original file. */
     if (!g_file_replace_contents (file, buf, size, NULL, FALSE,
                                   G_FILE_CREATE_NONE, NULL, NULL, error))
     {
-       g_object_unref (ostream);
-       g_free (buf);
-       g_assert (error == NULL || *error != NULL);
-       return FALSE;
+        GError *tmp_error = NULL;
+
+        g_object_unref (ostream);
+        g_free (buf);
+
+        /* Re-open the file for reading, to keep the internal state
+         * consistent. */
+        state->in = g_file_read (file, NULL, &tmp_error);
+
+        if (!state->in)
+        {
+            g_warning ("Error opening Ogg file for reading after write failure: %s",
+                       tmp_error->message);
+            g_clear_error (&tmp_error);
+            g_assert (error == NULL || *error != NULL);
+            return FALSE;
+        }
+
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
     }
 
     g_free (buf);
     g_object_unref (ostream);
 
+    /* Re-open the file, now that the write has completed. */
+    state->in = g_file_read (file, NULL, error);
+
+    if (!state->in)
+    {
+        g_assert (error == NULL || *error != NULL);
+        return FALSE;
+    }
+
+
     return TRUE;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]