Reworked error handling.
[ruby-vorbistagger.git] / ext / vcedit.c
index 10746706f71c97fbd0c620b4ca2d95f4d8d8be9b..22a8271afabfc84f559eddec87ad1c2042b0b0b1 100644 (file)
@@ -43,12 +43,12 @@ struct vcedit_state_St {
        char filename[PATH_MAX];
 
        FILE *in;
+       bool opened;
        long serial;
        unsigned char *mainbuf;
        unsigned char *bookbuf;
        int     mainlen;
        int     booklen;
-       const char *lasterror;
        char *vendor;
        int prevW;
        int extrapage;
@@ -120,16 +120,10 @@ vcedit_state_new (const char *filename)
        return state;
 }
 
-const char *
-vcedit_error (vcedit_state *state)
-{
-       return state->lasterror;
-}
-
 vorbis_comment *
 vcedit_comments (vcedit_state *state)
 {
-       return state->vc;
+       return state->opened ? state->vc : NULL;
 }
 
 static void
@@ -153,6 +147,7 @@ vcedit_clear_internals (vcedit_state *state)
        state->booklen = 0;
 
        state->serial = 0;
+       state->opened = false;
 }
 
 void
@@ -278,9 +273,10 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
        return _fetch_next_packet (s, p, page);
 }
 
-int
+vcedit_error
 vcedit_open (vcedit_state *state)
 {
+       vcedit_error ret;
        char *buffer;
        int bytes, i;
        int chunks = 0;
@@ -289,10 +285,8 @@ vcedit_open (vcedit_state *state)
        ogg_page og;
 
        state->in = fopen (state->filename, "rb");
-       if (!state->in) {
-               state->lasterror = "Cannot open file.";
-               return -1;
-       }
+       if (!state->in)
+               return VCEDIT_ERR_OPEN;
 
        ogg_sync_init (state->oy);
 
@@ -307,10 +301,7 @@ vcedit_open (vcedit_state *state)
 
                /* Bail if we don't find data in the first 40 kB */
                if (chunks++ >= 10) {
-                       if (bytes < CHUNKSIZE)
-                               state->lasterror = "Input truncated or empty.";
-                       else
-                               state->lasterror = "Input is not an Ogg bitstream.";
+                       ret = VCEDIT_ERR_INVAL;
 
                        goto err;
                }
@@ -323,17 +314,17 @@ vcedit_open (vcedit_state *state)
        vorbis_comment_init (state->vc);
 
        if (ogg_stream_pagein (state->os, &og) < 0) {
-               state->lasterror = "Error reading first page of Ogg bitstream.";
+               ret = VCEDIT_ERR_INVAL;
                goto err;
        }
 
        if (ogg_stream_packetout (state->os, &header_main) != 1) {
-               state->lasterror = "Error reading initial header packet.";
+               ret = VCEDIT_ERR_INVAL;
                goto err;
        }
 
        if (vorbis_synthesis_headerin (state->vi, state->vc, &header_main) < 0) {
-               state->lasterror = "Ogg bitstream does not contain vorbis data.";
+               ret = VCEDIT_ERR_INVAL;
                goto err;
        }
 
@@ -361,7 +352,7 @@ vcedit_open (vcedit_state *state)
                                                break;
 
                                        if (result == -1) {
-                                               state->lasterror = "Corrupt secondary header.";
+                                               ret = VCEDIT_ERR_INVAL;
                                                goto err;
                                        }
 
@@ -383,7 +374,7 @@ vcedit_open (vcedit_state *state)
                bytes = fread (buffer, 1, CHUNKSIZE, state->in);
 
                if (bytes == 0 && i < 2) {
-                       state->lasterror = "EOF before end of vorbis headers.";
+                       ret = VCEDIT_ERR_INVAL;
                        goto err;
                }
 
@@ -394,15 +385,17 @@ vcedit_open (vcedit_state *state)
        state->vendor = strdup (state->vc->vendor);
 
        /* Headers are done! */
-       return 0;
+       state->opened = true;
+
+       return VCEDIT_ERR_SUCCESS;
 
 err:
        vcedit_clear_internals (state);
 
-       return -1;
+       return ret;
 }
 
-int
+vcedit_error
 vcedit_write (vcedit_state *state)
 {
        ogg_stream_state streamout;
@@ -414,23 +407,22 @@ vcedit_write (vcedit_state *state)
        int s, result, bytes, needflush = 0, needout = 0;
        size_t tmp;
 
+       if (!state->opened)
+               return VCEDIT_ERR_INVAL;
+
        strcpy (tmpfile, state->filename);
        strcat (tmpfile, ".XXXXXX");
 
        s = mkstemp (tmpfile);
-       if (s == -1) {
-               state->lasterror = "Error writing stream to output. "
-                                  "Cannot open temporary file.";
-               return -1;
-       }
+       if (s == -1)
+               return VCEDIT_ERR_TMPFILE;
 
        out = fdopen (s, "wb");
        if (!out) {
                unlink (tmpfile);
                close (s);
-               state->lasterror = "Error writing stream to output. "
-                                  "Cannot open temporary file.";
-               return -1;
+
+               return VCEDIT_ERR_TMPFILE;
        }
 
        state->prevW = state->extrapage = state->eosin = 0;
@@ -548,9 +540,7 @@ vcedit_write (vcedit_state *state)
                        if (!result)
                 break;
 
-                       if (result < 0)
-                               state->lasterror = "Corrupt or missing data, continuing...";
-                       else {
+                       if (result >= 0) {
                                /* Don't bother going through the rest, we can just
                                 * write the page out now
                                 */
@@ -593,14 +583,11 @@ cleanup:
 
     state->mainbuf = state->bookbuf = NULL;
 
-       if (!state->eosin) {
-               state->lasterror = "Error writing stream to output. "
-                                  "Output stream may be corrupted or truncated.";
-               return -1;
-       }
+       if (!state->eosin)
+               return VCEDIT_ERR_INVAL;
 
        vcedit_clear_internals (state);
-       vcedit_open (state);
 
-       return 0;
+       return (vcedit_open (state) == VCEDIT_ERR_SUCCESS) ?
+              VCEDIT_ERR_SUCCESS : VCEDIT_ERR_REOPEN;
 }