X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=ext%2Fvcedit.c;h=414d6d060f31c0d98f6b3a4a12dfa18748e79904;hb=e04f6c2b90c9501fc613a130ee90863cc84f4a98;hp=cf63e7487217c7a36fcb479590328488928c7c63;hpb=d167e476209adeab15e067425b941509b1ed90f4;p=ruby-vorbistagger.git diff --git a/ext/vcedit.c b/ext/vcedit.c index cf63e74..414d6d0 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,19 +180,20 @@ _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]); } } @@ -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