projects
/
ruby-vorbistagger.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Handle short writes gracefully.
[ruby-vorbistagger.git]
/
ext
/
vcedit.c
diff --git
a/ext/vcedit.c
b/ext/vcedit.c
index 832f417b2b30519cba6661b3dfb063c52a43f925..b9650f8a157ed395281fece20874a1c24165b9df 100644
(file)
--- a/
ext/vcedit.c
+++ b/
ext/vcedit.c
@@
-40,8
+40,6
@@
struct vcedit_state_St {
vorbis_comment vc;
vorbis_info vi;
vorbis_comment vc;
vorbis_info vi;
- char filename[PATH_MAX];
-
FILE *in;
bool opened;
long serial;
FILE *in;
bool opened;
long serial;
@@
-53,6
+51,8
@@
struct vcedit_state_St {
int prevW;
int extrapage;
int eosin;
int prevW;
int extrapage;
int eosin;
+
+ char filename[0];
};
static void
};
static void
@@
-71,10
+71,12
@@
vcedit_state_free (vcedit_state *state)
}
static bool
}
static bool
-vcedit_state_init (vcedit_state *state)
+vcedit_state_init (vcedit_state *state
, const char *filename
)
{
state->refcount = 1;
{
state->refcount = 1;
+ strcpy (state->filename, filename);
+
return true;
}
return true;
}
@@
-82,21
+84,23
@@
vcedit_state *
vcedit_state_new (const char *filename)
{
vcedit_state *state;
vcedit_state_new (const char *filename)
{
vcedit_state *state;
+ size_t len;
- state = malloc (sizeof (vcedit_state));
+ len = strlen (filename);
+ if (len > PATH_MAX)
+ return NULL;
+
+ state = malloc (sizeof (vcedit_state) + len + 1);
if (!state)
return NULL;
memset (state, 0, sizeof (vcedit_state));
if (!state)
return NULL;
memset (state, 0, sizeof (vcedit_state));
- if (!vcedit_state_init (state)) {
+ if (!vcedit_state_init (state
, filename
)) {
vcedit_state_free (state);
return NULL;
}
vcedit_state_free (state);
return NULL;
}
- snprintf (state->filename, sizeof (state->filename),
- "%s", filename);
-
return state;
}
return state;
}
@@
-154,9
+158,8
@@
vcedit_state_unref (vcedit_state *state)
static void
_v_writestring (oggpack_buffer *o, char *s, int len)
{
static void
_v_writestring (oggpack_buffer *o, char *s, int len)
{
- while (len--)
{
+ while (len--)
oggpack_write (o, *s++, 8);
oggpack_write (o, *s++, 8);
- }
}
static int
}
static int
@@
-226,19
+229,18
@@
_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
int result, bytes;
result = ogg_stream_packetout (&s->os, p);
int result, bytes;
result = ogg_stream_packetout (&s->os, p);
-
- if (result > 0)
+ if (result == 1)
return 1;
if (s->eosin)
return 0;
return 1;
if (s->eosin)
return 0;
- while (ogg_sync_pageout (&s->oy, page)
<= 0
) {
+ while (ogg_sync_pageout (&s->oy, page)
!= 1
) {
buffer = ogg_sync_buffer (&s->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, s->in);
ogg_sync_wrote (&s->oy, bytes);
buffer = ogg_sync_buffer (&s->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, s->in);
ogg_sync_wrote (&s->oy, bytes);
- if (!bytes)
+ if (!bytes
&& feof (s->in)
)
return 0;
}
return 0;
}
@@
-259,12
+261,12
@@
vcedit_error
vcedit_open (vcedit_state *state)
{
vcedit_error ret;
vcedit_open (vcedit_state *state)
{
vcedit_error ret;
- char *buffer;
- int bytes, i;
- int chunks = 0;
ogg_packet *header;
ogg_packet header_main, header_comments, header_codebooks;
ogg_page og;
ogg_packet *header;
ogg_packet header_main, header_comments, header_codebooks;
ogg_page og;
+ char *buffer;
+ size_t bytes, total = 0;
+ int i = 0;
state->in = fopen (state->filename, "rb");
if (!state->in)
state->in = fopen (state->filename, "rb");
if (!state->in)
@@
-272,22
+274,21
@@
vcedit_open (vcedit_state *state)
ogg_sync_init (&state->oy);
ogg_sync_init (&state->oy);
- while (1) {
- buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
- bytes = fread (buffer, 1, CHUNKSIZE, state->in);
-
- ogg_sync_wrote (&state->oy, bytes);
-
- if (ogg_sync_pageout (&state->oy, &og) == 1)
- break;
-
+ do {
/* Bail if we don't find data in the first 40 kB */
/* Bail if we don't find data in the first 40 kB */
- if (
chunks++ >= 10
) {
+ if (
feof (state->in) || total >= (CHUNKSIZE * 10)
) {
ogg_sync_clear (&state->oy);
return VCEDIT_ERR_INVAL;
}
ogg_sync_clear (&state->oy);
return VCEDIT_ERR_INVAL;
}
- }
+
+ buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
+
+ bytes = fread (buffer, 1, CHUNKSIZE, state->in);
+ total += bytes;
+
+ ogg_sync_wrote (&state->oy, bytes);
+ } while (ogg_sync_pageout (&state->oy, &og) != 1);
state->serial = ogg_page_serialno (&og);
state->serial = ogg_page_serialno (&og);
@@
-314,48
+315,47
@@
vcedit_open (vcedit_state *state)
state->mainbuf = malloc (state->mainlen);
memcpy (state->mainbuf, header_main.packet, header_main.bytes);
state->mainbuf = malloc (state->mainlen);
memcpy (state->mainbuf, header_main.packet, header_main.bytes);
- i = 0;
header = &header_comments;
while (i < 2) {
while (i < 2) {
header = &header_comments;
while (i < 2) {
while (i < 2) {
- int result
= ogg_sync_pageout (&state->oy, &og)
;
+ int result;
+ result = ogg_sync_pageout (&state->oy, &og);
if (!result)
break; /* Too little data so far */
if (!result)
break; /* Too little data so far */
- if (result == 1) {
- ogg_stream_pagein (&state->os, &og);
-
- while (i < 2) {
- result = ogg_stream_packetout (&state->os, header);
+ if (result != 1)
+ continue;
- if (!result)
- break;
+ ogg_stream_pagein (&state->os, &og);
-
if (result == -1
) {
-
ret = VCEDIT_ERR_INVAL
;
- goto err;
- }
+
while (i < 2
) {
+
result = ogg_stream_packetout (&state->os, header)
;
+ if (!result)
+ break;
- vorbis_synthesis_headerin (&state->vi, &state->vc, header);
+ if (result != 1) {
+ ret = VCEDIT_ERR_INVAL;
+ goto err;
+ }
- if (i == 1) {
- state->booklen = header->bytes;
- state->bookbuf = malloc (state->booklen);
- memcpy (state->bookbuf, header->packet, header->bytes);
- }
+ vorbis_synthesis_headerin (&state->vi, &state->vc, header);
- i++;
- header = &header_codebooks;
+ if (i++ == 1) {
+ state->booklen = header->bytes;
+ state->bookbuf = malloc (state->booklen);
+ memcpy (state->bookbuf, header->packet, header->bytes);
}
}
+
+ header = &header_codebooks;
}
}
buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
}
}
buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
- if (
bytes == 0
&& i < 2) {
+ if (
!bytes && feof (state->in)
&& i < 2) {
ret = VCEDIT_ERR_INVAL;
goto err;
}
ret = VCEDIT_ERR_INVAL;
goto err;
}
@@
-377,6
+377,23
@@
err:
return ret;
}
return ret;
}
+static int
+write_data (const void *buf, size_t size, size_t nmemb, FILE *stream)
+{
+ while (nmemb > 0) {
+ size_t w;
+
+ w = fwrite (buf, size, nmemb, stream);
+ if (!w && ferror (stream))
+ return 0;
+
+ nmemb -= w;
+ buf += size * w;
+ }
+
+ return 1;
+}
+
vcedit_error
vcedit_write (vcedit_state *state)
{
vcedit_error
vcedit_write (vcedit_state *state)
{
@@
-387,7
+404,6
@@
vcedit_write (vcedit_state *state)
FILE *out;
char *buffer, tmpfile[PATH_MAX];
int s, result, bytes, needflush = 0, needout = 0;
FILE *out;
char *buffer, tmpfile[PATH_MAX];
int s, result, bytes, needflush = 0, needout = 0;
- size_t tmp;
if (!state->opened)
return VCEDIT_ERR_INVAL;
if (!state->opened)
return VCEDIT_ERR_INVAL;
@@
-430,12
+446,10
@@
vcedit_write (vcedit_state *state)
ogg_stream_packetin (&streamout, &header_codebooks);
while ((result = ogg_stream_flush (&streamout, &ogout))) {
ogg_stream_packetin (&streamout, &header_codebooks);
while ((result = ogg_stream_flush (&streamout, &ogout))) {
- tmp = fwrite (ogout.header, 1, ogout.header_len, out);
- if (tmp != (size_t) ogout.header_len)
+ if (!write_data (ogout.header, 1, ogout.header_len, out))
goto cleanup;
goto cleanup;
- tmp = fwrite (ogout.body, 1, ogout.body_len, out);
- if (tmp != (size_t) ogout.body_len)
+ if (!write_data (ogout.body, 1, ogout.body_len, out))
goto cleanup;
}
goto cleanup;
}
@@
-447,22
+461,18
@@
vcedit_write (vcedit_state *state)
if (needflush) {
if (ogg_stream_flush (&streamout, &ogout)) {
if (needflush) {
if (ogg_stream_flush (&streamout, &ogout)) {
- tmp = fwrite (ogout.header, 1, ogout.header_len, out);
- if (tmp != (size_t) ogout.header_len)
+ if (!write_data (ogout.header, 1, ogout.header_len, out))
goto cleanup;
goto cleanup;
- tmp = fwrite (ogout.body, 1, ogout.body_len, out);
- if (tmp != (size_t) ogout.body_len)
+ if (!write_data (ogout.body, 1, ogout.body_len, out))
goto cleanup;
}
} else if (needout) {
if (ogg_stream_pageout (&streamout, &ogout)) {
goto cleanup;
}
} else if (needout) {
if (ogg_stream_pageout (&streamout, &ogout)) {
- tmp = fwrite (ogout.header, 1, ogout.header_len, out);
- if (tmp != (size_t) ogout.header_len)
+ if (!write_data (ogout.header, 1, ogout.header_len, out))
goto cleanup;
goto cleanup;
- tmp = fwrite (ogout.body, 1, ogout.body_len, out);
- if (tmp != (size_t) ogout.body_len)
+ if (!write_data (ogout.body, 1, ogout.body_len, out))
goto cleanup;
}
}
goto cleanup;
}
}
@@
-490,61
+500,48
@@
vcedit_write (vcedit_state *state)
streamout.e_o_s = 1;
while (ogg_stream_flush (&streamout, &ogout)) {
streamout.e_o_s = 1;
while (ogg_stream_flush (&streamout, &ogout)) {
- tmp = fwrite (ogout.header, 1, ogout.header_len, out);
- if (tmp != (size_t) ogout.header_len)
+ if (!write_data (ogout.header, 1, ogout.header_len, out))
goto cleanup;
goto cleanup;
- tmp = fwrite (ogout.body, 1, ogout.body_len, out);
- if (tmp != (size_t) ogout.body_len)
+ if (!write_data (ogout.body, 1, ogout.body_len, out))
goto cleanup;
}
if (state->extrapage) {
goto cleanup;
}
if (state->extrapage) {
- tmp = fwrite (ogin.header, 1, ogin.header_len, out);
- if (tmp != (size_t) ogin.header_len)
+ if (!write_data (ogin.header, 1, ogin.header_len, out))
goto cleanup;
goto cleanup;
- tmp = fwrite (ogin.body, 1, ogin.body_len, out);
- if (tmp != (size_t) ogin.body_len)
+ if (!write_data (ogin.body, 1, ogin.body_len, out))
goto cleanup;
}
/* clear it, because not all paths to here do */
state->eosin = 0;
goto cleanup;
}
/* clear it, because not all paths to here do */
state->eosin = 0;
- while (!state->eosin) { /* We reached eos, not eof */
+ do {
/* We copy the rest of the stream (other logical streams)
* through, a page at a time.
*/
/* We copy the rest of the stream (other logical streams)
* through, a page at a time.
*/
- while (1) {
- result = ogg_sync_pageout (&state->oy, &ogout);
+ while ((result = ogg_sync_pageout (&state->oy, &ogout))) {
+ if (result != 1)
+ continue;
- if (!result)
- break;
-
- if (result >= 0) {
- /* Don't bother going through the rest, we can just
- * write the page out now
- */
- tmp = fwrite (ogout.header, 1, ogout.header_len, out);
- if (tmp != (size_t) ogout.header_len)
- goto cleanup;
+ /* Don't bother going through the rest, we can just
+ * write the page out now
+ */
+ if (!write_data (ogout.header, 1, ogout.header_len, out))
+ goto cleanup;
- tmp = fwrite (ogout.body, 1, ogout.body_len, out);
- if (tmp != (size_t) ogout.body_len)
- goto cleanup;
- }
+ if (!write_data (ogout.body, 1, ogout.body_len, out))
+ goto cleanup;
}
buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
ogg_sync_wrote (&state->oy, bytes);
}
buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
ogg_sync_wrote (&state->oy, bytes);
- if (!bytes) {
- state->eosin = 1;
- break;
- }
- }
+ state->eosin = !bytes && feof (state->in);
+ } while (!state->eosin);
fclose (out);
fclose (state->in);
fclose (out);
fclose (state->in);