X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=ext%2Fvcedit.c;h=f3ad2c95a1a1557468947739d46ec08838a70928;hb=3e0e120ba38a9bf52f3bb5cf47106919440c2452;hp=cf63e7487217c7a36fcb479590328488928c7c63;hpb=d167e476209adeab15e067425b941509b1ed90f4;p=ruby-vorbistagger.git diff --git a/ext/vcedit.c b/ext/vcedit.c index cf63e74..f3ad2c9 100644 --- a/ext/vcedit.c +++ b/ext/vcedit.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -41,6 +43,8 @@ struct vcedit_state_St { vorbis_info vi; FILE *in; + mode_t file_mode; + bool opened; long serial; unsigned char *mainbuf; @@ -163,11 +167,11 @@ _v_writestring (oggpack_buffer *o, char *s, int len) } static int -_commentheader_out (vorbis_comment *vc, char *vendor, ogg_packet *op) +_commentheader_out (vcedit_state *s, ogg_packet *op) { - int i; - oggpack_buffer opb; + size_t len; + int i; oggpack_writeinit (&opb); @@ -176,30 +180,31 @@ _commentheader_out (vorbis_comment *vc, char *vendor, ogg_packet *op) _v_writestring (&opb, "vorbis", 6); /* vendor */ - oggpack_write (&opb, strlen (vendor), 32); - _v_writestring (&opb, vendor, strlen (vendor)); + len = strlen (s->vendor); + oggpack_write (&opb, len, 32); + _v_writestring (&opb, s->vendor, len); /* comments */ - oggpack_write (&opb, vc->comments, 32); + oggpack_write (&opb, s->vc.comments, 32); - for (i = 0; i < vc->comments; i++) { - if (!vc->user_comments[i]) + for (i = 0; i < s->vc.comments; i++) { + if (!s->vc.user_comments[i]) oggpack_write (&opb, 0, 32); else { - oggpack_write (&opb, vc->comment_lengths[i], 32); - _v_writestring (&opb, vc->user_comments[i], - vc->comment_lengths[i]); + oggpack_write (&opb, s->vc.comment_lengths[i], 32); + _v_writestring (&opb, s->vc.user_comments[i], + s->vc.comment_lengths[i]); } } oggpack_write (&opb, 1, 1); - op->packet = _ogg_malloc (oggpack_bytes (&opb)); - memcpy (op->packet, opb.buffer, oggpack_bytes (&opb)); - op->bytes = oggpack_bytes (&opb); - op->b_o_s = 0; - op->e_o_s = 0; + op->packet = _ogg_malloc (op->bytes); + + memcpy (op->packet, opb.buffer, op->bytes); + + op->b_o_s = op->e_o_s = 0; op->granulepos = 0; oggpack_writeclear (&opb); @@ -264,6 +269,7 @@ vcedit_open (vcedit_state *s) ogg_packet *header; ogg_packet header_main, header_comments, header_codebooks; ogg_page og; + struct stat st; char *buffer; size_t bytes, total = 0; int i = 0; @@ -272,6 +278,8 @@ vcedit_open (vcedit_state *s) if (!s->in) return VCEDIT_ERR_OPEN; + s->file_mode = stat (s->filename, &st) ? 0664 : st.st_mode; + ogg_sync_init (&s->oy); do { @@ -403,6 +411,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) @@ -439,7 +448,7 @@ vcedit_write (vcedit_state *s) ogg_stream_init (&streamout, s->serial); - _commentheader_out (&s->vc, s->vendor, &header_comments); + _commentheader_out (s, &header_comments); ogg_stream_packetin (&streamout, &header_main); ogg_stream_packetin (&streamout, &header_comments); @@ -546,13 +555,21 @@ vcedit_write (vcedit_state *s) 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); + chmod (s->filename, s->file_mode); + } -cleanup: ogg_stream_clear (&streamout); /* We don't ogg_packet_clear() this, because the memory was