Close and remove the temporary file if vcedit_write() fails.
[ruby-vorbistagger.git] / ext / vcedit.c
index ce5cb10b56ee9ecadd2a4829b496a2ea990a491a..38ecb9f9d384818c84df6a0e96b85274fdd34767 100644 (file)
@@ -240,7 +240,7 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
                bytes = fread (buffer, 1, CHUNKSIZE, s->in);
                ogg_sync_wrote (&s->oy, bytes);
 
-               if (!bytes && feof (s->in))
+               if (!bytes && (feof (s->in) || ferror (s->in)))
                        return 0;
        }
 
@@ -276,7 +276,7 @@ vcedit_open (vcedit_state *s)
 
        do {
                /* Bail if we don't find data in the first 40 kB */
-               if (feof (s->in) || total >= (CHUNKSIZE * 10)) {
+               if (feof (s->in) || ferror (s->in) || total >= (CHUNKSIZE * 10)) {
                        ogg_sync_clear (&s->oy);
 
                        return VCEDIT_ERR_INVAL;
@@ -318,6 +318,11 @@ vcedit_open (vcedit_state *s)
        header = &header_comments;
 
        while (i < 2) {
+               if (feof (s->in) || ferror (s->in)) {
+                       ret = VCEDIT_ERR_INVAL;
+                       goto err;
+               }
+
                while (i < 2) {
                        int result;
 
@@ -353,13 +358,8 @@ vcedit_open (vcedit_state *s)
                }
 
                buffer = ogg_sync_buffer (&s->oy, CHUNKSIZE);
-               bytes = fread (buffer, 1, CHUNKSIZE, s->in);
-
-               if (!bytes && feof (s->in) && i < 2) {
-                       ret = VCEDIT_ERR_INVAL;
-                       goto err;
-               }
 
+               bytes = fread (buffer, 1, CHUNKSIZE, s->in);
                ogg_sync_wrote (&s->oy, bytes);
        }
 
@@ -403,6 +403,7 @@ vcedit_write (vcedit_state *s)
        ogg_int64_t granpos = 0;
        FILE *out;
        char *buffer, tmpfile[PATH_MAX];
+       bool success = false;
        int fd, result, bytes, needflush = 0, needout = 0;
 
        if (!s->opened)
@@ -540,16 +541,26 @@ vcedit_write (vcedit_state *s)
                bytes = fread (buffer, 1, CHUNKSIZE, s->in);
                ogg_sync_wrote (&s->oy, bytes);
 
+               if (ferror (s->in))
+                       goto cleanup;
+
                s->eosin = !bytes && feof (s->in);
        } while (!s->eosin);
 
-       fclose (out);
+       success = true;
+
+cleanup:
        fclose (s->in);
 
-       unlink (s->filename);
-       rename (tmpfile, s->filename);
+       if (!success) {
+               unlink (tmpfile);
+               fclose (out);
+       } else {
+               fclose (out);
+               unlink (s->filename);
+               rename (tmpfile, s->filename);
+       }
 
-cleanup:
        ogg_stream_clear (&streamout);
 
     /* We don't ogg_packet_clear() this, because the memory was