1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000-2009 Josh Coalson
3 * Copyright (C) 2011-2022 Xiph.Org Foundation
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdio.h> /* for FILE etc. */
25 #include <stdlib.h> /* for calloc() etc. */
26 #include <string.h> /* for memcmp() etc. */
27 #include "FLAC/assert.h"
28 #include "FLAC/metadata.h"
29 #include "share/alloc.h"
30 #include "share/compat.h"
31 #include "foreign_metadata.h"
32
33 #ifdef min
34 #undef min
35 #endif
36 #define min(x,y) ((x)<(y)?(x):(y))
37
38 const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[FLAC__FOREIGN_METADATA_NUMBER_OF_RECOGNIZED_APPLICATION_IDS] = { "aiff" , "riff", "w64 " };
39
unpack32be_(const FLAC__byte * b)40 static FLAC__uint32 unpack32be_(const FLAC__byte *b)
41 {
42 return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
43 }
44
unpack32le_(const FLAC__byte * b)45 static FLAC__uint32 unpack32le_(const FLAC__byte *b)
46 {
47 return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
48 }
49
unpack64le_(const FLAC__byte * b)50 static FLAC__uint64 unpack64le_(const FLAC__byte *b)
51 {
52 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);
53 }
54
55 /* copies 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */
copy_data_(FILE * fin,FILE * fout,size_t size,const char ** error,const char * const read_error,const char * const write_error)56 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)
57 {
58 FLAC__byte buffer[4096];
59 size_t left;
60 for(left = size; left > 0; ) {
61 size_t need = min(sizeof(buffer), left);
62 if(fread(buffer, 1, need, fin) < need) {
63 if(error) *error = read_error;
64 return false;
65 }
66 if(fwrite(buffer, 1, need, fout) < need) {
67 if(error) *error = write_error;
68 return false;
69 }
70 left -= need;
71 }
72 return true;
73 }
74
75 /* compare 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */
compare_data_(FILE * fin,FILE * fout,size_t size,const char ** error,const char * const read_error,const char * const write_error,const char * const compare_error)76 static FLAC__bool compare_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error, const char * const compare_error)
77 {
78 FLAC__byte buffer_in[4096];
79 FLAC__byte buffer_out[4096]; /* sizes need to be the same */
80 size_t left;
81 for(left = size; left > 0; ) {
82 size_t need = min(sizeof(buffer_in), left);
83 if(fread(buffer_in, 1, need, fin) < need) {
84 if(error) *error = read_error;
85 return false;
86 }
87 if(fread(buffer_out, 1, need, fout) < need) {
88 if(error) *error = write_error;
89 return false;
90 }
91 if(memcmp(buffer_in, buffer_out, need)) {
92 if(error) *error = compare_error;
93 return false;
94 }
95 left -= need;
96 }
97 return true;
98 }
99
append_block_(foreign_metadata_t * fm,FLAC__off_t offset,FLAC__uint32 size,const char ** error)100 static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error)
101 {
102 foreign_block_t *fb = safe_realloc_nofree_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
103 if(fb) {
104 fb[fm->num_blocks].offset = offset;
105 fb[fm->num_blocks].size = size;
106 fm->num_blocks++;
107 fm->blocks = fb;
108 return true;
109 }
110 if(error) *error = "out of memory";
111 return false;
112 }
113
read_from_aiff_(foreign_metadata_t * fm,FILE * f,const char ** error)114 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
115 {
116 FLAC__byte buffer[12];
117 FLAC__off_t offset, eof_offset;
118 if((offset = ftello(f)) < 0) {
119 if(error) *error = "ftello() error (001)";
120 return false;
121 }
122 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
123 if(error) *error = "unsupported FORM layout (002)";
124 return false;
125 }
126 if(!append_block_(fm, offset, 12, error))
127 return false;
128 eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32be_(buffer+4);
129 while(!feof(f)) {
130 FLAC__uint32 size;
131 if((offset = ftello(f)) < 0) {
132 if(error) *error = "ftello() error (003)";
133 return false;
134 }
135 if((size = fread(buffer, 1, 8, f)) < 8) {
136 if(size == 0 && feof(f))
137 break;
138 if(error) *error = "invalid AIFF file (004)";
139 return false;
140 }
141 size = unpack32be_(buffer+4);
142 /* check if pad byte needed */
143 if(size & 1)
144 size++;
145 if(!memcmp(buffer, "COMM", 4)) {
146 if(fm->format_block) {
147 if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
148 return false;
149 }
150 if(fm->audio_block) {
151 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
152 return false;
153 }
154 fm->format_block = fm->num_blocks;
155 }
156 else if(!memcmp(buffer, "SSND", 4)) {
157 if(fm->audio_block) {
158 if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
159 return false;
160 }
161 if(!fm->format_block) {
162 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
163 return false;
164 }
165 fm->audio_block = fm->num_blocks;
166 /* read #offset bytes */
167 if(fread(buffer+8, 1, 4, f) < 4) {
168 if(error) *error = "invalid AIFF file (009)";
169 return false;
170 }
171 fm->ssnd_offset_size = unpack32be_(buffer+8);
172 if(fseeko(f, -4, SEEK_CUR) < 0) {
173 if(error) *error = "invalid AIFF file: seek error (010)";
174 return false;
175 }
176 /* WATCHOUT: For SSND we ignore the blockSize and are not saving any
177 * unaligned part at the end of the chunk. In retrospect it is pretty
178 * pointless to save the unaligned data before the PCM but now it is
179 * done and cast in stone.
180 */
181 }
182 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
183 return false;
184 /* skip to next chunk */
185 if(fseeko(f, size, SEEK_CUR) < 0) {
186 if(error) *error = "invalid AIFF file: seek error (011)";
187 return false;
188 }
189 }
190 if(eof_offset != ftello(f)) {
191 if(error) *error = "invalid AIFF file: unexpected EOF (012)";
192 return false;
193 }
194 if(!fm->format_block) {
195 if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
196 return false;
197 }
198 if(!fm->audio_block) {
199 if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
200 return false;
201 }
202 return true;
203 }
204
read_from_wave_(foreign_metadata_t * fm,FILE * f,const char ** error)205 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
206 {
207 FLAC__byte buffer[12];
208 FLAC__off_t offset, eof_offset = -1, ds64_data_size = -1;
209 if((offset = ftello(f)) < 0) {
210 if(error) *error = "ftello() error (001)";
211 return false;
212 }
213 if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) {
214 if(error) *error = "unsupported RIFF layout (002)";
215 return false;
216 }
217 if(!memcmp(buffer, "RF64", 4))
218 fm->is_rf64 = true;
219 if(fm->is_rf64 && sizeof(FLAC__off_t) < 8) {
220 if(error) *error = "RF64 is not supported on this compile (r00)";
221 return false;
222 }
223 if(!append_block_(fm, offset, 12, error))
224 return false;
225 if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffff) {
226 eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32le_(buffer+4);
227 if(eof_offset & 1) /* fix odd RIFF size */
228 eof_offset++;
229 }
230 while(!feof(f)) {
231 FLAC__off_t size;
232 if((offset = ftello(f)) < 0) {
233 if(error) *error = "ftello() error (003)";
234 return false;
235 }
236 if((size = fread(buffer, 1, 8, f)) < 8) {
237 if(size == 0 && feof(f))
238 break;
239 if(error) *error = "invalid WAVE file (004)";
240 return false;
241 }
242 size = unpack32le_(buffer+4);
243 /* check if pad byte needed */
244 if(size & 1)
245 size++;
246 if(!memcmp(buffer, "fmt ", 4)) {
247 if(fm->format_block) {
248 if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
249 return false;
250 }
251 if(fm->audio_block) {
252 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
253 return false;
254 }
255 fm->format_block = fm->num_blocks;
256 }
257 else if(!memcmp(buffer, "data", 4)) {
258 if(fm->audio_block) {
259 if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
260 return false;
261 }
262 if(!fm->format_block) {
263 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
264 return false;
265 }
266 fm->audio_block = fm->num_blocks;
267 if(fm->is_rf64 && fm->num_blocks < 2) {
268 if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)";
269 return false;
270 }
271 }
272 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
273 return false;
274 /* parse ds64 chunk if necessary */
275 if(fm->is_rf64 && fm->num_blocks == 2) {
276 FLAC__byte buffer2[7*4];
277 if(memcmp(buffer, "ds64", 4)) {
278 if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)";
279 return false;
280 }
281 /* unpack the size again since we don't want the padding byte effect */
282 size = unpack32le_(buffer+4);
283 if(size < (FLAC__off_t)sizeof(buffer2)) {
284 if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)";
285 return false;
286 }
287 if(size > (FLAC__off_t)sizeof(buffer2)) {
288 if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)";
289 return false;
290 }
291 if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) {
292 if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)";
293 return false;
294 }
295 ds64_data_size = (FLAC__off_t)unpack64le_(buffer2+8);
296 if(ds64_data_size == (FLAC__off_t)(-1)) {
297 if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)";
298 return false;
299 }
300 /* check if pad byte needed */
301 if(ds64_data_size & 1)
302 ds64_data_size++;
303 /* @@@ [2^63 limit] */
304 if(ds64_data_size < 0) {
305 if(error) *error = "RF64 file too large (r09)";
306 return false;
307 }
308 if(unpack32le_(buffer2+24)) {
309 if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)";
310 return false;
311 }
312 eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack64le_(buffer2);
313 /* @@@ [2^63 limit] */
314 if((FLAC__off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) {
315 if(error) *error = "RF64 file too large (r07)";
316 return false;
317 }
318 }
319 else { /* skip to next chunk */
320 if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffff) {
321 if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) {
322 if(error) *error = "invalid RF64 file: seek error (r10)";
323 return false;
324 }
325 }
326 else {
327 if(fseeko(f, size, SEEK_CUR) < 0) {
328 if(error) *error = "invalid WAVE file: seek error (009)";
329 return false;
330 }
331 }
332 }
333 }
334 if(fm->is_rf64 && eof_offset == (FLAC__off_t)(-1)) {
335 if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)";
336 return false;
337 }
338 if(eof_offset != ftello(f)) {
339 if(error) *error = "invalid WAVE file: unexpected EOF (010)";
340 return false;
341 }
342 if(!fm->format_block) {
343 if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
344 return false;
345 }
346 if(!fm->audio_block) {
347 if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
348 return false;
349 }
350 return true;
351 }
352
read_from_wave64_(foreign_metadata_t * fm,FILE * f,const char ** error)353 static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
354 {
355 FLAC__byte buffer[40];
356 FLAC__off_t offset, eof_offset = -1;
357 if((offset = ftello(f)) < 0) {
358 if(error) *error = "ftello() error (001)";
359 return false;
360 }
361 if(
362 fread(buffer, 1, 40, f) < 40 ||
363 /* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
364 memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) ||
365 /* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
366 memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)
367 ) {
368 if(error) *error = "unsupported Wave64 layout (002)";
369 return false;
370 }
371 if(sizeof(FLAC__off_t) < 8) {
372 if(error) *error = "Wave64 is not supported on this compile (r00)";
373 return false;
374 }
375 if(!append_block_(fm, offset, 40, error))
376 return false;
377 eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
378 while(!feof(f)) {
379 FLAC__uint64 size;
380 if((offset = ftello(f)) < 0) {
381 if(error) *error = "ftello() error (003)";
382 return false;
383 }
384 if((size = fread(buffer, 1, 24, f)) < 24) {
385 if(size == 0 && feof(f))
386 break;
387 if(error) *error = "invalid Wave64 file (004)";
388 return false;
389 }
390 size = unpack64le_(buffer+16);
391 /* check if pad bytes needed */
392 if(size & 7)
393 size = (size+7) & (~((FLAC__uint64)7));
394 /* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
395 if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
396 if(fm->format_block) {
397 if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
398 return false;
399 }
400 if(fm->audio_block) {
401 if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
402 return false;
403 }
404 fm->format_block = fm->num_blocks;
405 }
406 /* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
407 else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
408 if(fm->audio_block) {
409 if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
410 return false;
411 }
412 if(!fm->format_block) {
413 if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
414 return false;
415 }
416 fm->audio_block = fm->num_blocks;
417 }
418 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))
419 return false;
420 /* skip to next chunk */
421 if(fseeko(f, size-24, SEEK_CUR) < 0) {
422 if(error) *error = "invalid Wave64 file: seek error (009)";
423 return false;
424 }
425 }
426 if(eof_offset != ftello(f)) {
427 if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
428 return false;
429 }
430 if(!fm->format_block) {
431 if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
432 return false;
433 }
434 if(!fm->audio_block) {
435 if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
436 return false;
437 }
438 return true;
439 }
440
write_to_flac_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__Metadata_SimpleIterator * it,const char ** error)441 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
442 {
443 FLAC__byte buffer[4];
444 const uint32_t ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
445 size_t block_num = 0;
446 FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
447 while(block_num < fm->num_blocks) {
448 /* find next matching padding block */
449 do {
450 /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */
451 if(!FLAC__metadata_simple_iterator_next(it)) {
452 if(error) *error = "no matching PADDING block found (004)";
453 return false;
454 }
455 } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
456 if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
457 if(error) *error = "PADDING block with wrong size found (005)";
458 return false;
459 }
460 /* transfer chunk into APPLICATION block */
461 /* first set up the file pointers */
462 if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
463 if(error) *error = "seek failed in WAVE/AIFF file (006)";
464 return false;
465 }
466 if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
467 if(error) *error = "seek failed in FLAC file (007)";
468 return false;
469 }
470 /* update the type */
471 buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
472 if(FLAC__metadata_simple_iterator_is_last(it))
473 buffer[0] |= 0x80; /*MAGIC number*/
474 if(fwrite(buffer, 1, 1, fout) < 1) {
475 if(error) *error = "write failed in FLAC file (008)";
476 return false;
477 }
478 /* length stays the same so skip over it */
479 if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
480 if(error) *error = "seek failed in FLAC file (009)";
481 return false;
482 }
483 /* write the APPLICATION ID */
484 memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
485 if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
486 if(error) *error = "write failed in FLAC file (010)";
487 return false;
488 }
489 /* transfer the foreign metadata */
490 if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
491 return false;
492 block_num++;
493 }
494 return true;
495 }
496
read_from_flac_(foreign_metadata_t * fm,FILE * f,FLAC__Metadata_SimpleIterator * it,const char ** error)497 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
498 {
499 FLAC__byte id[4], buffer[32];
500 FLAC__off_t offset;
501 FLAC__uint32 length;
502 FLAC__bool first_block = true, type_found = false, ds64_found = false;
503
504 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
505
506 while(FLAC__metadata_simple_iterator_next(it)) {
507 if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
508 continue;
509 if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
510 if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
511 return false;
512 }
513 if(first_block) {
514 uint32_t i;
515 for(i = 0; i < FLAC__FOREIGN_METADATA_NUMBER_OF_RECOGNIZED_APPLICATION_IDS; i++)
516 if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[i], sizeof(id)) == 0) {
517 fm->type = i;
518 first_block = false;
519 }
520 if(first_block) /* means no first foreign metadata block was found yet */
521 continue;
522 }
523 else if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
524 continue;
525 offset = FLAC__metadata_simple_iterator_get_block_offset(it);
526 length = FLAC__metadata_simple_iterator_get_block_length(it);
527 /* skip over header and app ID */
528 offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
529 offset += sizeof(id);
530 /* look for format or audio blocks */
531 if(fseeko(f, offset, SEEK_SET) < 0) {
532 if(error) *error = "seek error (003)";
533 return false;
534 }
535 if(fread(buffer, 1, 4, f) != 4) {
536 if(error) *error = "read error (004)";
537 return false;
538 }
539 if(fm->num_blocks == 0) { /* first block? */
540 /* Initialize bools */
541 fm->is_wavefmtex = 0;
542 fm->is_aifc = 0;
543 fm->is_sowt = 0;
544 fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
545
546 if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
547 type_found = true;
548 else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
549 type_found = true;
550 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) {
551 type_found = true;
552 if(fread(buffer+4, 1, 8, f) != 8) {
553 if(error) *error = "read error (020)";
554 return false;
555 }
556 fm->is_aifc = 0 == memcmp(buffer+8, "AIFC", 4);
557 }
558 else {
559 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
560 return false;
561 }
562 }
563 else if(!type_found) {
564 FLAC__ASSERT(0);
565 /* double protection: */
566 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
567 return false;
568 }
569 else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
570 if(!memcmp(buffer, "fmt ", 4)) {
571 if(fm->format_block) {
572 if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
573 return false;
574 }
575 if(fm->audio_block) {
576 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
577 return false;
578 }
579 fm->format_block = fm->num_blocks;
580 if(fread(buffer+4, 1, 8, f) != 8) {
581 if(error) *error = "read error (020)";
582 return false;
583 }
584 fm->is_wavefmtex = 0 == memcmp(buffer+8, "\xfe\xff", 2);
585 }
586 else if(!memcmp(buffer, "data", 4)) {
587 if(fm->audio_block) {
588 if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
589 return false;
590 }
591 if(!fm->format_block) {
592 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
593 return false;
594 }
595 fm->audio_block = fm->num_blocks;
596 }
597 else if(fm->is_rf64 && fm->num_blocks == 1) {
598 if(memcmp(buffer, "ds64", 4)) {
599 if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
600 return false;
601 }
602 ds64_found = true;
603 }
604 }
605 else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
606 if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
607 if(fm->format_block) {
608 if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
609 return false;
610 }
611 if(fm->audio_block) {
612 if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
613 return false;
614 }
615 fm->format_block = fm->num_blocks;
616 }
617 else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
618 if(fm->audio_block) {
619 if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
620 return false;
621 }
622 if(!fm->format_block) {
623 if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
624 return false;
625 }
626 fm->audio_block = fm->num_blocks;
627 }
628 }
629 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
630 if(!memcmp(buffer, "COMM", 4)) {
631 if(fm->format_block) {
632 if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
633 return false;
634 }
635 if(fm->audio_block) {
636 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
637 return false;
638 }
639 fm->format_block = fm->num_blocks;
640 if(fm->is_aifc) {
641 if(fread(buffer+4, 1, 26, f) != 26) {
642 if(error) *error = "read error (020)";
643 return false;
644 }
645 fm->is_sowt = 0 == memcmp(buffer+26, "sowt", 2);
646 fm->aifc_comm_length = length;
647 }
648 }
649 else if(!memcmp(buffer, "SSND", 4)) {
650 if(fm->audio_block) {
651 if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
652 return false;
653 }
654 if(!fm->format_block) {
655 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
656 return false;
657 }
658 fm->audio_block = fm->num_blocks;
659 /* read SSND offset size */
660 if(fread(buffer+4, 1, 8, f) != 8) {
661 if(error) *error = "read error (020)";
662 return false;
663 }
664 fm->ssnd_offset_size = unpack32be_(buffer+8);
665 }
666 }
667 else {
668 FLAC__ASSERT(0);
669 /* double protection: */
670 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
671 return false;
672 }
673 if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
674 return false;
675 }
676 if(fm->is_rf64 && !ds64_found) {
677 if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
678 return false;
679 }
680 if(!fm->format_block) {
681 if(error)
682 *error =
683 fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
684 fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
685 "invalid AIFF file: missing \"COMM\" chunk (026)";
686 return false;
687 }
688 if(!fm->audio_block) {
689 if(error)
690 *error =
691 fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
692 fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
693 "invalid AIFF file: missing \"SSND\" chunk (029)";
694 return false;
695 }
696 return true;
697 }
698
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)699 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)
700 {
701 size_t i;
702 if(fseeko(fout, offset1, SEEK_SET) < 0) {
703 if(error) *error = "seek failed in WAVE/AIFF file";
704 return false;
705 }
706
707 /* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64 */
708 for(i = fm->is_rf64?2:1; i < fm->format_block; i++) {
709 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
710 if(error) *error = "seek failed in FLAC file";
711 return false;
712 }
713 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
714 return false;
715 }
716
717 if(fm->is_aifc) {
718 /* Need to restore compression type name */
719 if(fseeko(fout, 30, SEEK_CUR) < 0) {
720 if(error) *error = "seek failed in AIFF-C file";
721 return false;
722 }
723 if(fseeko(fin, fm->blocks[i].offset+30, SEEK_SET) < 0) {
724 if(error) *error = "seek failed in FLAC file";
725 return false;
726 }
727 if(!copy_data_(fin, fout, fm->aifc_comm_length-34, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
728 return false;
729 /* Now seek back */
730 if(fseeko(fout, ((FLAC__int32)(fm->aifc_comm_length) * -1) + 4, SEEK_CUR) < 0) {
731 if(error) *error = "seek failed in AIFF-C file";
732 return false;
733 }
734 }
735 if(fseeko(fout, offset2, SEEK_SET) < 0) {
736 if(error) *error = "seek failed in WAVE/AIFF file (006)";
737 return false;
738 }
739 for(i = fm->format_block+1; i < fm->audio_block; i++) {
740 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
741 if(error) *error = "seek failed in FLAC file";
742 return false;
743 }
744 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
745 return false;
746 }
747 if(fseeko(fout, offset3, SEEK_SET) < 0) {
748 if(error) *error = "seek failed in WAVE/AIFF file";
749 return false;
750 }
751 for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
752 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
753 if(error) *error = "seek failed in FLAC file";
754 return false;
755 }
756 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
757 return false;
758 }
759 return true;
760 }
761
compare_with_iff_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__off_t offset3,const char ** error)762 static FLAC__bool compare_with_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__off_t offset3, const char **error)
763 {
764 size_t i;
765
766 /* Compare blocks before audio data */
767 for(i = 0; i <= (fm->audio_block); i++) {
768 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
769 if(error) *error = "seek failed in FLAC file";
770 return false;
771 }
772 if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file",
773 i==0?"stored main chunk length differs from written length":(
774 i==fm->format_block?"stored foreign format block differs from written block. Perhaps the file is being restored to a different format than that of the original file":(
775 i==fm->audio_block?"stored audio length differs from written length. Perhaps the file changed in length after being originally encoded":"restore of foreign metadata failed"))))
776 return false;
777 }
778
779 /* Seek beyond audio */
780 if(fseeko(fout, offset3, SEEK_SET) < 0) {
781 if(error) *error = "seek failed in WAVE/AIFF file";
782 return false;
783 }
784 for(; i < fm->num_blocks; i++) {
785 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
786 if(error) *error = "seek failed in FLAC file";
787 return false;
788 }
789 if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file", "restore of foreign metadata failed"))
790 return false;
791 }
792 return true;
793 }
794
flac__foreign_metadata_new(foreign_block_type_t type)795 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
796 {
797 /* calloc() to zero all the member variables */
798 foreign_metadata_t *x = calloc(sizeof(foreign_metadata_t), 1);
799 if(x) {
800 x->type = type;
801 x->is_rf64 = false;
802 }
803 return x;
804 }
805
flac__foreign_metadata_delete(foreign_metadata_t * fm)806 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
807 {
808 if(fm) {
809 if(fm->blocks)
810 free(fm->blocks);
811 free(fm);
812 }
813 }
814
flac__foreign_metadata_read_from_aiff(foreign_metadata_t * fm,const char * filename,const char ** error)815 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
816 {
817 FLAC__bool ok;
818 FILE *f = flac_fopen(filename, "rb");
819 if(!f) {
820 if(error) *error = "can't open AIFF file for reading (000)";
821 return false;
822 }
823 ok = read_from_aiff_(fm, f, error);
824 fclose(f);
825 return ok;
826 }
827
flac__foreign_metadata_read_from_wave(foreign_metadata_t * fm,const char * filename,const char ** error)828 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
829 {
830 FLAC__bool ok;
831 FILE *f = flac_fopen(filename, "rb");
832 if(!f) {
833 if(error) *error = "can't open WAVE file for reading (000)";
834 return false;
835 }
836 ok = read_from_wave_(fm, f, error);
837 fclose(f);
838 return ok;
839 }
840
flac__foreign_metadata_read_from_wave64(foreign_metadata_t * fm,const char * filename,const char ** error)841 FLAC__bool flac__foreign_metadata_read_from_wave64(foreign_metadata_t *fm, const char *filename, const char **error)
842 {
843 FLAC__bool ok;
844 FILE *f = flac_fopen(filename, "rb");
845 if(!f) {
846 if(error) *error = "can't open Wave64 file for reading (000)";
847 return false;
848 }
849 ok = read_from_wave64_(fm, f, error);
850 fclose(f);
851 return ok;
852 }
853
flac__foreign_metadata_write_to_flac(foreign_metadata_t * fm,const char * infilename,const char * outfilename,const char ** error)854 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
855 {
856 FLAC__bool ok;
857 FILE *fin, *fout;
858 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
859 if(!it) {
860 if(error) *error = "out of memory (000)";
861 return false;
862 }
863 if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
864 if(error) *error = "can't initialize iterator (001)";
865 FLAC__metadata_simple_iterator_delete(it);
866 return false;
867 }
868 if(0 == (fin = flac_fopen(infilename, "rb"))) {
869 if(error) *error = "can't open WAVE/AIFF file for reading (002)";
870 FLAC__metadata_simple_iterator_delete(it);
871 return false;
872 }
873 if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
874 if(error) *error = "can't open FLAC file for updating (003)";
875 FLAC__metadata_simple_iterator_delete(it);
876 fclose(fin);
877 return false;
878 }
879 ok = write_to_flac_(fm, fin, fout, it, error);
880 FLAC__metadata_simple_iterator_delete(it);
881 fclose(fin);
882 fclose(fout);
883 return ok;
884 }
885
flac__foreign_metadata_read_from_flac(foreign_metadata_t * fm,const char * filename,const char ** error)886 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
887 {
888 FLAC__bool ok;
889 FILE *f;
890 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
891 if(!it) {
892 if(error) *error = "out of memory (000)";
893 return false;
894 }
895 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
896 if(error) *error = "can't initialize iterator (001)";
897 FLAC__metadata_simple_iterator_delete(it);
898 return false;
899 }
900 if(0 == (f = flac_fopen(filename, "rb"))) {
901 if(error) *error = "can't open FLAC file for reading (002)";
902 FLAC__metadata_simple_iterator_delete(it);
903 return false;
904 }
905 ok = read_from_flac_(fm, f, it, error);
906 FLAC__metadata_simple_iterator_delete(it);
907 fclose(f);
908 return ok;
909 }
910
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)911 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)
912 {
913 FLAC__bool ok;
914 FILE *fin, *fout;
915 if(0 == (fin = flac_fopen(infilename, "rb"))) {
916 if(error) *error = "can't open FLAC file for reading (000)";
917 return false;
918 }
919 if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
920 if(error) *error = "can't open WAVE/AIFF file for updating (001)";
921 fclose(fin);
922 return false;
923 }
924 ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);
925 fclose(fin);
926 fclose(fout);
927 return ok;
928 }
929
flac__foreign_metadata_compare_with_iff(foreign_metadata_t * fm,const char * infilename,const char * outfilename,FLAC__off_t offset3,const char ** error)930 FLAC__bool flac__foreign_metadata_compare_with_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, FLAC__off_t offset3, const char **error)
931 {
932 FLAC__bool ok;
933 FILE *fin, *fout;
934 if(0 == (fin = flac_fopen(infilename, "rb"))) {
935 if(error) *error = "can't open FLAC file for reading";
936 return false;
937 }
938 if(0 == (fout = flac_fopen(outfilename, "rb"))) {
939 if(error) *error = "can't open WAVE/AIFF file for comparing";
940 fclose(fin);
941 return false;
942 }
943 ok = compare_with_iff_(fm, fin, fout, offset3, error);
944 fclose(fin);
945 fclose(fout);
946 return ok;
947 }
948