File easytag-revert-open-handle-ogg.patch of Package easytag
diff --git a/src/tags/vcedit.c b/src/tags/vcedit.c
index b19b920..8d3dae4 100644
--- a/src/tags/vcedit.c
+++ b/src/tags/vcedit.c
@@ -35,6 +35,7 @@
struct _EtOggState
{
/*< private >*/
+ GFileInputStream *in;
#ifdef ENABLE_SPEEX
SpeexHeader *si;
#endif
@@ -125,6 +126,11 @@ vcedit_clear_internals (EtOggState *state)
}
#endif /* ENABLE_OPUS */
+ if (state->in)
+ {
+ g_object_unref (state->in);
+ }
+
memset (state, 0, sizeof (*state));
}
@@ -239,7 +245,6 @@ _blocksize (EtOggState *s,
static gboolean
_fetch_next_packet (EtOggState *s,
- GInputStream *istream,
ogg_packet *p,
ogg_page *page,
GError **error)
@@ -269,8 +274,8 @@ _fetch_next_packet (EtOggState *s,
while (ogg_sync_pageout (s->oy, page) <= 0)
{
buffer = ogg_sync_buffer (s->oy, CHUNKSIZE);
- bytes = g_input_stream_read (istream, buffer, CHUNKSIZE, NULL,
- error);
+ bytes = g_input_stream_read (G_INPUT_STREAM (s->in), buffer,
+ CHUNKSIZE, NULL, error);
ogg_sync_wrote (s->oy, bytes);
if(bytes == 0)
@@ -303,7 +308,7 @@ _fetch_next_packet (EtOggState *s,
g_assert (error == NULL || *error == NULL);
ogg_stream_pagein (s->os, page);
- return _fetch_next_packet (s, istream, p, page, error);
+ return _fetch_next_packet (s, p, page, error);
}
}
@@ -492,13 +497,14 @@ vcedit_open (EtOggState *state,
return FALSE;
}
+ state->in = istream;
state->oy = g_slice_new (ogg_sync_state);
ogg_sync_init (state->oy);
while(1)
{
buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
- bytes = g_input_stream_read (G_INPUT_STREAM (istream), buffer,
+ bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
CHUNKSIZE, NULL, error);
if (bytes == -1)
{
@@ -748,7 +754,7 @@ vcedit_open (EtOggState *state,
}
buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
- bytes = g_input_stream_read (G_INPUT_STREAM (istream), buffer,
+ bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
CHUNKSIZE, NULL, error);
if (bytes == -1)
@@ -770,14 +776,11 @@ vcedit_open (EtOggState *state,
/* Headers are done! */
g_assert (error == NULL || *error == NULL);
- /* TODO: Handle error during stream close. */
- g_object_unref (istream);
return TRUE;
err:
g_assert (error == NULL || *error != NULL);
- g_object_unref (istream);
vcedit_clear_internals (state);
return FALSE;
}
@@ -800,7 +803,6 @@ vcedit_write (EtOggState *state,
glong bytes;
gboolean needflush = FALSE;
gboolean needout = FALSE;
- GFileInputStream *istream;
GOutputStream *ostream;
gchar *buf;
gsize size;
@@ -808,22 +810,11 @@ vcedit_write (EtOggState *state,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- istream = g_file_read (file, NULL, error);
-
- if (!istream)
- {
- g_assert (error == NULL || *error != NULL);
- return FALSE;
- }
-
- fileinfo = g_file_input_stream_query_info (istream,
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
- NULL, error);
-
+ fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE, NULL, error);
if (!fileinfo)
{
g_assert (error == NULL || *error != NULL);
- g_object_unref (istream);
return FALSE;
}
@@ -884,8 +875,7 @@ vcedit_write (EtOggState *state,
}
}
- while (_fetch_next_packet (state, G_INPUT_STREAM (istream), &op, &ogin,
- error))
+ while (_fetch_next_packet (state, &op, &ogin, error))
{
if (needflush)
{
@@ -1061,7 +1051,7 @@ vcedit_write (EtOggState *state,
{
/* We copy the rest of the stream (other logical streams)
* through, a page at a time. */
- while (1)
+ while(1)
{
result = ogg_sync_pageout (state->oy, &ogout);
@@ -1100,7 +1090,7 @@ vcedit_write (EtOggState *state,
buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
- bytes = g_input_stream_read (G_INPUT_STREAM (istream), buffer,
+ bytes = g_input_stream_read (G_INPUT_STREAM (state->in), buffer,
CHUNKSIZE, NULL, error);
if (bytes == -1)
@@ -1118,19 +1108,11 @@ vcedit_write (EtOggState *state,
}
}
+
cleanup:
ogg_stream_clear (&streamout);
ogg_packet_clear (&header_comments);
- if (!g_input_stream_close (G_INPUT_STREAM (istream), 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 (istream);
g_free (state->mainbuf);
g_free (state->bookbuf);
state->mainbuf = state->bookbuf = NULL;
@@ -1164,13 +1146,41 @@ 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))
{
+ 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;
}
@@ -1178,6 +1188,16 @@ cleanup:
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;
}