X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fflac%2Fforeign_metadata.c;h=837292616215a98228aa40fa24d9cfe7b5dac1c2;hb=5705b4d7b2c3c5311138e9f4b66658c51f3cc22b;hp=9487e9b3898b662f6d3ffae6665c41bb3d089d8e;hpb=f178b143238fd8fd34f38e2f0d8bddeca4de530f;p=platform%2Fupstream%2Fflac.git diff --git a/src/flac/foreign_metadata.c b/src/flac/foreign_metadata.c index 9487e9b..8372926 100644 --- a/src/flac/foreign_metadata.c +++ b/src/flac/foreign_metadata.c @@ -1,5 +1,5 @@ /* flac - Command-line FLAC encoder/decoder - * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,27 +11,22 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #if HAVE_CONFIG_H # include #endif -#if defined _MSC_VER || defined __MINGW32__ -#include /* for off_t */ -#if _MSC_VER <= 1600 /* @@@ [2G limit] */ -#define fseeko fseek -#define ftello ftell -#endif -#endif #include /* for FILE etc. */ #include /* for calloc() etc. */ #include /* for memcmp() etc. */ #include "FLAC/assert.h" #include "FLAC/metadata.h" +#include "share/alloc.h" +#include "share/compat.h" #include "foreign_metadata.h" #ifdef min @@ -40,7 +35,7 @@ #define min(x,y) ((x)<(y)?(x):(y)) -static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "AIFF" , "RIFF" }; +static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[3] = { "aiff" , "riff", "w64 " }; static FLAC__uint32 unpack32be_(const FLAC__byte *b) { @@ -52,9 +47,15 @@ static FLAC__uint32 unpack32le_(const FLAC__byte *b) return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24); } +static FLAC__uint64 unpack64le_(const FLAC__byte *b) +{ + return (FLAC__uint64)b[0] + ((FLAC__uint64)b[1]<<8) + ((FLAC__uint64)b[2]<<16) + ((FLAC__uint64)b[3]<<24) + ((FLAC__uint64)b[4]<<32) + ((FLAC__uint64)b[5]<<40) + ((FLAC__uint64)b[6]<<48) + ((FLAC__uint64)b[7]<<56); +} + +/* copies 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */ static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error) { - static FLAC__byte buffer[4096]; + FLAC__byte buffer[4096]; size_t left; for(left = size; left > 0; ) { size_t need = min(sizeof(buffer), left); @@ -71,15 +72,14 @@ static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **er return true; } -static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error) +static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error) { - foreign_block_t *fb = realloc(fm->blocks, sizeof(foreign_block_t) * (fm->num_blocks+1)); + foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/); if(fb) { fb[fm->num_blocks].offset = offset; fb[fm->num_blocks].size = size; fm->num_blocks++; fm->blocks = fb; -/*fprintf(stderr,"@@@@@@ appended: block#%u offset=%d size=%u\n",fm->num_blocks-1,(int)fm->blocks[fm->num_blocks-1].offset,(unsigned)fm->blocks[fm->num_blocks-1].size);*/ return true; } if(error) *error = "out of memory"; @@ -89,7 +89,7 @@ static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error) { FLAC__byte buffer[12]; - off_t offset, eof_offset; + FLAC__off_t offset, eof_offset; if((offset = ftello(f)) < 0) { if(error) *error = "ftello() error (001)"; return false; @@ -100,8 +100,7 @@ static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char ** } if(!append_block_(fm, offset, 12, error)) return false; - eof_offset = 8 + unpack32be_(buffer+4); -/*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/ + eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32be_(buffer+4); while(!feof(f)) { FLAC__uint32 size; if((offset = ftello(f)) < 0) { @@ -149,10 +148,15 @@ static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char ** if(error) *error = "invalid AIFF file: seek error (010)"; return false; } + /* WATCHOUT: For SSND we ignore the blockSize and are not saving any + * unaligned part at the end of the chunk. In retrospect it is pretty + * pointless to save the unaligned data before the PCM but now it is + * done and cast in stone. + */ } if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error)) return false; -/*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/ + /* skip to next chunk */ if(fseeko(f, size, SEEK_CUR) < 0) { if(error) *error = "invalid AIFF file: seek error (011)"; return false; @@ -176,19 +180,25 @@ static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char ** static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error) { FLAC__byte buffer[12]; - off_t offset, eof_offset; + FLAC__off_t offset, eof_offset = -1, ds64_data_size = -1; if((offset = ftello(f)) < 0) { if(error) *error = "ftello() error (001)"; return false; } - if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) { + if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) { if(error) *error = "unsupported RIFF layout (002)"; return false; } + if(!memcmp(buffer, "RF64", 4)) + fm->is_rf64 = true; + if(fm->is_rf64 && sizeof(FLAC__off_t) < 8) { + if(error) *error = "RF64 is not supported on this compile (r00)"; + return false; + } if(!append_block_(fm, offset, 12, error)) return false; - eof_offset = 8 + unpack32le_(buffer+4); -/*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/ + if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffffu) + eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32le_(buffer+4); while(!feof(f)) { FLAC__uint32 size; if((offset = ftello(f)) < 0) { @@ -226,15 +236,77 @@ static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char ** return false; } fm->audio_block = fm->num_blocks; + if(fm->is_rf64 && fm->num_blocks < 2) { + if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)"; + return false; + } } if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error)) return false; -/*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/ - if(fseeko(f, size, SEEK_CUR) < 0) { - if(error) *error = "invalid WAVE file: seek error (009)"; - return false; + /* parse ds64 chunk if necessary */ + if(fm->is_rf64 && fm->num_blocks == 2) { + FLAC__byte buffer2[7*4]; + if(memcmp(buffer, "ds64", 4)) { + if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)"; + return false; + } + /* unpack the size again since we don't want the padding byte effect */ + size = unpack32le_(buffer+4); + if(size < sizeof(buffer2)) { + if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)"; + return false; + } + if(size > sizeof(buffer2)) { + if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)"; + return false; + } + if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) { + if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)"; + return false; + } + ds64_data_size = (FLAC__off_t)unpack64le_(buffer2+8); + if(ds64_data_size == (FLAC__off_t)(-1)) { + if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)"; + return false; + } + /* check if pad byte needed */ + if(ds64_data_size & 1) + ds64_data_size++; + /* @@@ [2^63 limit] */ + if(ds64_data_size < 0) { + if(error) *error = "RF64 file too large (r09)"; + return false; + } + if(unpack32le_(buffer2+24)) { + if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)"; + return false; + } + eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack64le_(buffer2); + /* @@@ [2^63 limit] */ + if((FLAC__off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) { + if(error) *error = "RF64 file too large (r07)"; + return false; + } + } + else { /* skip to next chunk */ + if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffffu) { + if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) { + if(error) *error = "invalid RF64 file: seek error (r10)"; + return false; + } + } + else { + if(fseeko(f, size, SEEK_CUR) < 0) { + if(error) *error = "invalid WAVE file: seek error (009)"; + return false; + } + } } } + if(fm->is_rf64 && eof_offset == (FLAC__off_t)(-1)) { + if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)"; + return false; + } if(eof_offset != ftello(f)) { if(error) *error = "invalid WAVE file: unexpected EOF (010)"; return false; @@ -250,6 +322,94 @@ static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char ** return true; } +static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error) +{ + FLAC__byte buffer[40]; + FLAC__off_t offset, eof_offset = -1; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (001)"; + return false; + } + if( + fread(buffer, 1, 40, f) < 40 || + /* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */ + memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) || + /* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */ + memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16) + ) { + if(error) *error = "unsupported Wave64 layout (002)"; + return false; + } + if(sizeof(FLAC__off_t) < 8) { + if(error) *error = "Wave64 is not supported on this compile (r00)"; + return false; + } + if(!append_block_(fm, offset, 40, error)) + return false; + eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */ + while(!feof(f)) { + FLAC__uint64 size; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (003)"; + return false; + } + if((size = fread(buffer, 1, 24, f)) < 24) { + if(size == 0 && feof(f)) + break; + if(error) *error = "invalid Wave64 file (004)"; + return false; + } + size = unpack64le_(buffer+16); + /* check if pad bytes needed */ + if(size & 7) + size = (size+7) & (~((FLAC__uint64)7)); + /* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */ + if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) { + if(fm->format_block) { + if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)"; + return false; + } + fm->format_block = fm->num_blocks; + } + /* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */ + else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) { + if(fm->audio_block) { + if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)"; + return false; + } + fm->audio_block = fm->num_blocks; + } + if(!append_block_(fm, offset, memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)? (FLAC__uint32)size : 16+8, error)) + return false; + /* skip to next chunk */ + if(fseeko(f, size-24, SEEK_CUR) < 0) { + if(error) *error = "invalid Wave64 file: seek error (009)"; + return false; + } + } + if(eof_offset != ftello(f)) { + if(error) *error = "invalid Wave64 file: unexpected EOF (010)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)"; + return false; + } + if(!fm->audio_block) { + if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)"; + return false; + } + return true; +} + static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error) { FLAC__byte buffer[4]; @@ -269,7 +429,6 @@ static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, if(error) *error = "PADDING block with wrong size found (005)"; return false; } -/*fprintf(stderr,"@@@@@@ flac offset = %d\n",(int)FLAC__metadata_simple_iterator_get_block_offset(it));*/ /* transfer chunk into APPLICATION block */ /* first set up the file pointers */ if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) { @@ -310,8 +469,8 @@ static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error) { FLAC__byte id[4], buffer[12]; - off_t offset; - FLAC__bool type_found = false; + FLAC__off_t offset; + FLAC__bool type_found = false, ds64_found = false; FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8); @@ -319,7 +478,7 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION) continue; if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) { - if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (003)"; + if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)"; return false; } if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id))) @@ -329,16 +488,19 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8; offset += sizeof(id); /* look for format or audio blocks */ - if(fseek(f, offset, SEEK_SET) < 0) { - if(error) *error = "seek error (004)"; + if(fseeko(f, offset, SEEK_SET) < 0) { + if(error) *error = "seek error (003)"; return false; } if(fread(buffer, 1, 4, f) != 4) { - if(error) *error = "read error (005)"; + if(error) *error = "read error (004)"; return false; } - if(fm->num_blocks == 0) { - if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && 0 == memcmp(buffer, "RIFF", 4)) + if(fm->num_blocks == 0) { /* first block? */ + fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4); + if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64)) + type_found = true; + else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */ type_found = true; else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) type_found = true; @@ -376,32 +538,63 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat } fm->audio_block = fm->num_blocks; } + else if(fm->is_rf64 && fm->num_blocks == 1) { + if(memcmp(buffer, "ds64", 4)) { + if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)"; + return false; + } + ds64_found = true; + } + } + else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) { + if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */ + if(fm->format_block) { + if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)"; + return false; + } + fm->format_block = fm->num_blocks; + } + else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */ + if(fm->audio_block) { + if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)"; + return false; + } + fm->audio_block = fm->num_blocks; + } } else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) { if(!memcmp(buffer, "COMM", 4)) { if(fm->format_block) { - if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (011)"; + if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)"; return false; } if(fm->audio_block) { - if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)"; + if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)"; return false; } fm->format_block = fm->num_blocks; } else if(!memcmp(buffer, "SSND", 4)) { if(fm->audio_block) { - if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (013)"; + if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)"; return false; } if(!fm->format_block) { - if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)"; + if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)"; return false; } fm->audio_block = fm->num_blocks; /* read SSND offset size */ if(fread(buffer+4, 1, 8, f) != 8) { - if(error) *error = "read error (015)"; + if(error) *error = "read error (020)"; return false; } fm->ssnd_offset_size = unpack32be_(buffer+8); @@ -410,35 +603,48 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat else { FLAC__ASSERT(0); /* double protection: */ - if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (016)"; + if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)"; return false; } if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error)) return false; } if(!type_found) { - if(error) *error = "no foreign metadata found (017)"; + if(error) *error = "no foreign metadata found (022)"; + return false; + } + if(fm->is_rf64 && !ds64_found) { + if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)"; return false; } if(!fm->format_block) { - if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)"; + if(error) + *error = + fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" : + fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" : + "invalid AIFF file: missing \"COMM\" chunk (026)"; return false; } if(!fm->audio_block) { - if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)"; + if(error) + *error = + fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" : + fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" : + "invalid AIFF file: missing \"SSND\" chunk (029)"; return false; } return true; } -static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, off_t offset1, off_t offset2, off_t offset3, const char **error) +static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__off_t offset1, FLAC__off_t offset2, FLAC__off_t offset3, const char **error) { size_t i; if(fseeko(fout, offset1, SEEK_SET) < 0) { if(error) *error = "seek failed in WAVE/AIFF file (002)"; return false; } - for(i = 1; i < fm->format_block; i++) { + /* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64 */ + for(i = fm->is_rf64?2:1; i < fm->format_block; i++) { if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { if(error) *error = "seek failed in FLAC file (003)"; return false; @@ -475,9 +681,12 @@ static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, o foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type) { - foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1); - if(x) + /* calloc() to zero all the member variables */ + foreign_metadata_t *x = calloc(sizeof(foreign_metadata_t), 1); + if(x) { x->type = type; + x->is_rf64 = false; + } return x; } @@ -493,7 +702,7 @@ void flac__foreign_metadata_delete(foreign_metadata_t *fm) FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error) { FLAC__bool ok; - FILE *f = fopen(filename, "rb"); + FILE *f = flac_fopen(filename, "rb"); if(!f) { if(error) *error = "can't open AIFF file for reading (000)"; return false; @@ -506,7 +715,7 @@ FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const c FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error) { FLAC__bool ok; - FILE *f = fopen(filename, "rb"); + FILE *f = flac_fopen(filename, "rb"); if(!f) { if(error) *error = "can't open WAVE file for reading (000)"; return false; @@ -516,6 +725,19 @@ FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const c return ok; } +FLAC__bool flac__foreign_metadata_read_from_wave64(foreign_metadata_t *fm, const char *filename, const char **error) +{ + FLAC__bool ok; + FILE *f = flac_fopen(filename, "rb"); + if(!f) { + if(error) *error = "can't open Wave64 file for reading (000)"; + return false; + } + ok = read_from_wave64_(fm, f, error); + fclose(f); + return ok; +} + FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error) { FLAC__bool ok; @@ -530,12 +752,12 @@ FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const ch FLAC__metadata_simple_iterator_delete(it); return false; } - if(0 == (fin = fopen(infilename, "rb"))) { + if(0 == (fin = flac_fopen(infilename, "rb"))) { if(error) *error = "can't open WAVE/AIFF file for reading (002)"; FLAC__metadata_simple_iterator_delete(it); return false; } - if(0 == (fout = fopen(outfilename, "r+b"))) { + if(0 == (fout = flac_fopen(outfilename, "r+b"))) { if(error) *error = "can't open FLAC file for updating (003)"; FLAC__metadata_simple_iterator_delete(it); fclose(fin); @@ -562,7 +784,7 @@ FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const c FLAC__metadata_simple_iterator_delete(it); return false; } - if(0 == (f = fopen(filename, "rb"))) { + if(0 == (f = flac_fopen(filename, "rb"))) { if(error) *error = "can't open FLAC file for reading (002)"; FLAC__metadata_simple_iterator_delete(it); return false; @@ -573,15 +795,15 @@ FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const c return ok; } -FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error) +FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, FLAC__off_t offset1, FLAC__off_t offset2, FLAC__off_t offset3, const char **error) { FLAC__bool ok; FILE *fin, *fout; - if(0 == (fin = fopen(infilename, "rb"))) { + if(0 == (fin = flac_fopen(infilename, "rb"))) { if(error) *error = "can't open FLAC file for reading (000)"; return false; } - if(0 == (fout = fopen(outfilename, "r+b"))) { + if(0 == (fout = flac_fopen(outfilename, "r+b"))) { if(error) *error = "can't open WAVE/AIFF file for updating (001)"; fclose(fin); return false;