1 /* libFLAC - Free Lossless Audio Codec library
2 * Copyright (C) 2001-2009 Josh Coalson
3 * Copyright (C) 2011-2023 Xiph.Org Foundation
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * - Neither the name of the Xiph.org Foundation nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdarg.h>
42
43 #include <sys/stat.h> /* for stat(), maybe chmod() */
44
45 #include "private/metadata.h"
46
47 #include "FLAC/assert.h"
48 #include "FLAC/stream_decoder.h"
49 #include "share/alloc.h"
50 #include "share/compat.h"
51 #include "share/macros.h"
52 #include "private/macros.h"
53 #include "private/memory.h"
54
55 /* Alias the first (in share/alloc.h) to the second (in src/libFLAC/memory.c). */
56 #define safe_malloc_mul_2op_ safe_malloc_mul_2op_p
57
58 /****************************************************************************
59 *
60 * Local function declarations
61 *
62 ***************************************************************************/
63
64 static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, uint32_t bytes);
65 static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, uint32_t bytes);
66 static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, uint32_t bytes);
67 static FLAC__uint32 unpack_uint32_(FLAC__byte *b, uint32_t bytes);
68 static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, uint32_t bytes);
69 static FLAC__uint64 unpack_uint64_(FLAC__byte *b, uint32_t bytes);
70
71 static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator);
72 static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block);
73 static FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, uint32_t *length);
74 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block);
75 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block);
76 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, uint32_t block_length);
77 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, uint32_t block_length);
78 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, uint32_t block_length);
79 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry, uint32_t max_length);
80 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_VorbisComment *block, uint32_t block_length);
81 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track);
82 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block);
83 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block);
84 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, uint32_t block_length);
85
86 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
87 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
88 static FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block);
89 static FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block);
90 static FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block);
91 static FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, uint32_t block_length);
92 static FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, uint32_t block_length);
93 static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block);
94 static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block);
95 static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block);
96 static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block);
97 static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, uint32_t block_length);
98
99 static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
100 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, uint32_t padding_length, FLAC__bool padding_is_last);
101 static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append);
102
103 static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator);
104 static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator);
105
106 static uint32_t seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb);
107 static uint32_t seek_to_first_metadata_block_(FILE *f);
108
109 static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append);
110 static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, FLAC__off_t fixup_is_last_flag_offset, FLAC__bool backup);
111
112 static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
113 static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
114 static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status);
115 static FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status);
116
117 static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
118 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
119 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename);
120
121 static FLAC__bool get_file_stats_(const char *filename, struct flac_stat_s *stats);
122 static void set_file_stats_(const char *filename, struct flac_stat_s *stats);
123
124 static int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence);
125 static FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle);
126
127 static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status);
128
129
130 #ifdef FLAC__VALGRIND_TESTING
local__fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)131 static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
132 {
133 size_t ret = fwrite(ptr, size, nmemb, stream);
134 if(!ferror(stream))
135 fflush(stream);
136 return ret;
137 }
138 #else
139 #define local__fwrite fwrite
140 #endif
141
142 /****************************************************************************
143 *
144 * Level 0 implementation
145 *
146 ***************************************************************************/
147
148 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
149 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
150 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
151
152 typedef struct {
153 FLAC__bool got_error;
154 FLAC__StreamMetadata *object;
155 } level0_client_data;
156
get_one_metadata_block_(const char * filename,FLAC__MetadataType type)157 static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
158 {
159 level0_client_data cd;
160 FLAC__StreamDecoder *decoder;
161
162 FLAC__ASSERT(0 != filename);
163
164 cd.got_error = false;
165 cd.object = 0;
166
167 decoder = FLAC__stream_decoder_new();
168
169 if(0 == decoder)
170 return 0;
171
172 FLAC__stream_decoder_set_md5_checking(decoder, false);
173 FLAC__stream_decoder_set_metadata_ignore_all(decoder);
174 FLAC__stream_decoder_set_metadata_respond(decoder, type);
175
176 if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) {
177 (void)FLAC__stream_decoder_finish(decoder);
178 FLAC__stream_decoder_delete(decoder);
179 return 0;
180 }
181
182 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
183 (void)FLAC__stream_decoder_finish(decoder);
184 FLAC__stream_decoder_delete(decoder);
185 if(0 != cd.object)
186 FLAC__metadata_object_delete(cd.object);
187 return 0;
188 }
189
190 (void)FLAC__stream_decoder_finish(decoder);
191 FLAC__stream_decoder_delete(decoder);
192
193 return cd.object;
194 }
195
FLAC__metadata_get_streaminfo(const char * filename,FLAC__StreamMetadata * streaminfo)196 FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
197 {
198 FLAC__StreamMetadata *object;
199
200 FLAC__ASSERT(0 != filename);
201 FLAC__ASSERT(0 != streaminfo);
202
203 object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO);
204
205 if (object) {
206 /* can just copy the contents since STREAMINFO has no internal structure */
207 *streaminfo = *object;
208 FLAC__metadata_object_delete(object);
209 return true;
210 }
211 else {
212 return false;
213 }
214 }
215
FLAC__metadata_get_tags(const char * filename,FLAC__StreamMetadata ** tags)216 FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
217 {
218 FLAC__ASSERT(0 != filename);
219 FLAC__ASSERT(0 != tags);
220
221 *tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT);
222
223 return 0 != *tags;
224 }
225
FLAC__metadata_get_cuesheet(const char * filename,FLAC__StreamMetadata ** cuesheet)226 FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet)
227 {
228 FLAC__ASSERT(0 != filename);
229 FLAC__ASSERT(0 != cuesheet);
230
231 *cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET);
232
233 return 0 != *cuesheet;
234 }
235
write_callback_(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)236 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
237 {
238 (void)decoder, (void)frame, (void)buffer, (void)client_data;
239
240 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
241 }
242
metadata_callback_(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)243 void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
244 {
245 level0_client_data *cd = (level0_client_data *)client_data;
246 (void)decoder;
247
248 /*
249 * we assume we only get here when the one metadata block we were
250 * looking for was passed to us
251 */
252 if(!cd->got_error && 0 == cd->object) {
253 if(0 == (cd->object = FLAC__metadata_object_clone(metadata)))
254 cd->got_error = true;
255 }
256 }
257
error_callback_(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)258 void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
259 {
260 level0_client_data *cd = (level0_client_data *)client_data;
261 (void)decoder;
262
263 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
264 cd->got_error = true;
265 }
266
FLAC__metadata_get_picture(const char * filename,FLAC__StreamMetadata ** picture,FLAC__StreamMetadata_Picture_Type type,const char * mime_type,const FLAC__byte * description,uint32_t max_width,uint32_t max_height,uint32_t max_depth,uint32_t max_colors)267 FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, uint32_t max_width, uint32_t max_height, uint32_t max_depth, uint32_t max_colors)
268 {
269 FLAC__Metadata_SimpleIterator *it;
270 FLAC__uint64 max_area_seen = 0;
271 FLAC__uint64 max_depth_seen = 0;
272
273 FLAC__ASSERT(0 != filename);
274 FLAC__ASSERT(0 != picture);
275
276 *picture = 0;
277
278 it = FLAC__metadata_simple_iterator_new();
279 if(0 == it)
280 return false;
281 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
282 FLAC__metadata_simple_iterator_delete(it);
283 return false;
284 }
285 do {
286 if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
287 FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
288 if(0 != obj) {
289 FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
290
291 /* check constraints */
292 if(
293 (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
294 (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
295 (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
296 obj->data.picture.width <= max_width &&
297 obj->data.picture.height <= max_height &&
298 obj->data.picture.depth <= max_depth &&
299 obj->data.picture.colors <= max_colors &&
300 (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
301 ) {
302 if(*picture)
303 FLAC__metadata_object_delete(*picture);
304 *picture = obj;
305 max_area_seen = area;
306 max_depth_seen = obj->data.picture.depth;
307 }
308 else {
309 FLAC__metadata_object_delete(obj);
310 }
311 }
312 else
313 break;
314 }
315 } while(FLAC__metadata_simple_iterator_next(it));
316
317 FLAC__metadata_simple_iterator_delete(it);
318
319 return (0 != *picture);
320 }
321
322
323 /****************************************************************************
324 *
325 * Level 1 implementation
326 *
327 ***************************************************************************/
328
329 #define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4)
330 /* 1 for initial offset, +4 for our own personal use */
331
332 struct FLAC__Metadata_SimpleIterator {
333 FILE *file;
334 char *filename, *tempfile_path_prefix;
335 struct flac_stat_s stats;
336 FLAC__bool has_stats;
337 FLAC__bool is_writable;
338 FLAC__Metadata_SimpleIteratorStatus status;
339 FLAC__off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
340 FLAC__off_t first_offset; /* this is the offset to the STREAMINFO block */
341 uint32_t depth;
342 /* this is the metadata block header of the current block we are pointing to: */
343 FLAC__bool is_last;
344 FLAC__MetadataType type;
345 uint32_t length;
346 };
347
348 FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = {
349 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK",
350 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT",
351 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE",
352 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE",
353 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE",
354 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA",
355 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR",
356 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR",
357 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR",
358 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR",
359 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR",
360 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR",
361 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR"
362 };
363
364
FLAC__metadata_simple_iterator_new(void)365 FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void)
366 {
367 FLAC__Metadata_SimpleIterator *iterator = calloc(1, sizeof(FLAC__Metadata_SimpleIterator));
368
369 if(0 != iterator) {
370 iterator->file = 0;
371 iterator->filename = 0;
372 iterator->tempfile_path_prefix = 0;
373 iterator->has_stats = false;
374 iterator->is_writable = false;
375 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
376 iterator->first_offset = iterator->offset[0] = -1;
377 iterator->depth = 0;
378 }
379
380 return iterator;
381 }
382
simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator * iterator)383 static void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator)
384 {
385 FLAC__ASSERT(0 != iterator);
386
387 if(0 != iterator->file) {
388 fclose(iterator->file);
389 iterator->file = 0;
390 if(iterator->has_stats)
391 set_file_stats_(iterator->filename, &iterator->stats);
392 }
393 if(0 != iterator->filename) {
394 free(iterator->filename);
395 iterator->filename = 0;
396 }
397 if(0 != iterator->tempfile_path_prefix) {
398 free(iterator->tempfile_path_prefix);
399 iterator->tempfile_path_prefix = 0;
400 }
401 }
402
FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator * iterator)403 FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator)
404 {
405 FLAC__ASSERT(0 != iterator);
406
407 simple_iterator_free_guts_(iterator);
408 free(iterator);
409 }
410
FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator * iterator)411 FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator)
412 {
413 FLAC__Metadata_SimpleIteratorStatus status;
414
415 FLAC__ASSERT(0 != iterator);
416
417 status = iterator->status;
418 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
419 return status;
420 }
421
simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator * iterator,FLAC__bool read_only)422 static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool read_only)
423 {
424 uint32_t ret;
425
426 FLAC__ASSERT(0 != iterator);
427
428 if(read_only || 0 == (iterator->file = flac_fopen(iterator->filename, "r+b"))) {
429 iterator->is_writable = false;
430 if(read_only || errno == EACCES) {
431 if(0 == (iterator->file = flac_fopen(iterator->filename, "rb"))) {
432 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
433 return false;
434 }
435 }
436 else {
437 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
438 return false;
439 }
440 }
441 else {
442 iterator->is_writable = true;
443 }
444
445 ret = seek_to_first_metadata_block_(iterator->file);
446 switch(ret) {
447 case 0:
448 iterator->depth = 0;
449 iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file);
450 ret = read_metadata_block_header_(iterator);
451 /* The first metadata block must be a streaminfo. If this is not the
452 * case, the file is invalid and assumptions made elsewhere in the
453 * code are invalid */
454 if(iterator->type != FLAC__METADATA_TYPE_STREAMINFO) {
455 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
456 return false;
457 }
458 return ret;
459 case 1:
460 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
461 return false;
462 case 2:
463 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
464 return false;
465 case 3:
466 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE;
467 return false;
468 default:
469 FLAC__ASSERT(0);
470 return false;
471 }
472 }
473
474 #if 0
475 @@@ If we decide to finish implementing this, put this comment back in metadata.h
476 /*
477 * The 'tempfile_path_prefix' allows you to specify a directory where
478 * tempfiles should go. Remember that if your metadata edits cause the
479 * FLAC file to grow, the entire file will have to be rewritten. If
480 * 'tempfile_path_prefix' is NULL, the temp file will be written in the
481 * same directory as the original FLAC file. This makes replacing the
482 * original with the tempfile fast but requires extra space in the same
483 * partition for the tempfile. If space is a problem, you can pass a
484 * directory name belonging to a different partition in
485 * 'tempfile_path_prefix'. Note that you should use the forward slash
486 * '/' as the directory separator. A trailing slash is not needed; it
487 * will be added automatically.
488 */
489 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix);
490 #endif
491
FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator * iterator,const char * filename,FLAC__bool read_only,FLAC__bool preserve_file_stats)492 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats)
493 {
494 const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'flac_rename(...)' for what it will take to finish implementing this */
495
496 FLAC__ASSERT(0 != iterator);
497 FLAC__ASSERT(0 != filename);
498
499 simple_iterator_free_guts_(iterator);
500
501 if(!read_only && preserve_file_stats)
502 iterator->has_stats = get_file_stats_(filename, &iterator->stats);
503
504 if(0 == (iterator->filename = strdup(filename))) {
505 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
506 return false;
507 }
508 if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) {
509 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
510 return false;
511 }
512
513 return simple_iterator_prime_input_(iterator, read_only);
514 }
515
FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator * iterator)516 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator)
517 {
518 FLAC__ASSERT(0 != iterator);
519 FLAC__ASSERT(0 != iterator->file);
520
521 return iterator->is_writable;
522 }
523
FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator * iterator)524 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator)
525 {
526 FLAC__ASSERT(0 != iterator);
527 FLAC__ASSERT(0 != iterator->file);
528 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
529
530 if(iterator->is_last)
531 return false;
532
533 if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) {
534 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
535 return false;
536 }
537
538 iterator->offset[iterator->depth] = ftello(iterator->file);
539
540 return read_metadata_block_header_(iterator);
541 }
542
FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator * iterator)543 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator)
544 {
545 FLAC__off_t this_offset;
546
547 FLAC__ASSERT(0 != iterator);
548 FLAC__ASSERT(0 != iterator->file);
549 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
550
551 if(iterator->offset[iterator->depth] == iterator->first_offset)
552 return false;
553
554 if(0 != fseeko(iterator->file, iterator->first_offset, SEEK_SET)) {
555 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
556 return false;
557 }
558 this_offset = iterator->first_offset;
559 if(!read_metadata_block_header_(iterator))
560 return false;
561
562 /* we ignore any error from ftello() and catch it in fseeko() */
563 while(ftello(iterator->file) + (FLAC__off_t)iterator->length < iterator->offset[iterator->depth]) {
564 if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) {
565 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
566 return false;
567 }
568 this_offset = ftello(iterator->file);
569 if(!read_metadata_block_header_(iterator))
570 return false;
571 }
572
573 iterator->offset[iterator->depth] = this_offset;
574
575 return true;
576 }
577
578 /*@@@@add to tests*/
FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator * iterator)579 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator)
580 {
581 FLAC__ASSERT(0 != iterator);
582 FLAC__ASSERT(0 != iterator->file);
583 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
584
585 return iterator->is_last;
586 }
587
588 /*@@@@add to tests*/
FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator * iterator)589 FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator)
590 {
591 FLAC__ASSERT(0 != iterator);
592 FLAC__ASSERT(0 != iterator->file);
593 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
594
595 return (off_t)iterator->offset[iterator->depth];
596 }
597
FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator * iterator)598 FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator)
599 {
600 FLAC__ASSERT(0 != iterator);
601 FLAC__ASSERT(0 != iterator->file);
602 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
603
604 return iterator->type;
605 }
606
607 /*@@@@add to tests*/
FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator * iterator)608 FLAC_API uint32_t FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator)
609 {
610 FLAC__ASSERT(0 != iterator);
611 FLAC__ASSERT(0 != iterator->file);
612 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
613
614 return iterator->length;
615 }
616
617 /*@@@@add to tests*/
FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator * iterator,FLAC__byte * id)618 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id)
619 {
620 const uint32_t id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
621
622 FLAC__ASSERT(0 != iterator);
623 FLAC__ASSERT(0 != iterator->file);
624 FLAC__ASSERT(0 != id);
625 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
626
627 if(iterator->type != FLAC__METADATA_TYPE_APPLICATION) {
628 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
629 return false;
630 }
631
632 if(fread(id, 1, id_bytes, iterator->file) != id_bytes) {
633 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
634 return false;
635 }
636
637 /* back up */
638 if(0 != fseeko(iterator->file, -((int)id_bytes), SEEK_CUR)) {
639 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
640 return false;
641 }
642
643 return true;
644 }
645
FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator * iterator)646 FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator)
647 {
648 FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type);
649
650 FLAC__ASSERT(0 != iterator);
651 FLAC__ASSERT(0 != iterator->file);
652 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
653
654 if(0 != block) {
655 block->is_last = iterator->is_last;
656 block->length = iterator->length;
657
658 if(!read_metadata_block_data_(iterator, block)) {
659 FLAC__metadata_object_delete(block);
660 return 0;
661 }
662
663 /* back up to the beginning of the block data to stay consistent */
664 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
665 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
666 FLAC__metadata_object_delete(block);
667 return 0;
668 }
669 }
670 else
671 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
672
673 return block;
674 }
675
FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator * iterator,FLAC__StreamMetadata * block,FLAC__bool use_padding)676 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding)
677 {
678 FLAC__ASSERT_DECLARATION(FLAC__off_t debug_target_offset = iterator->offset[iterator->depth];)
679 FLAC__bool ret;
680
681 FLAC__ASSERT(0 != iterator);
682 FLAC__ASSERT(0 != iterator->file);
683 FLAC__ASSERT(0 != block);
684 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
685
686 if(!iterator->is_writable) {
687 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
688 return false;
689 }
690
691 if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) {
692 if(iterator->type != block->type) {
693 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
694 return false;
695 }
696 }
697
698 block->is_last = iterator->is_last;
699
700 if(iterator->length == block->length)
701 return write_metadata_block_stationary_(iterator, block);
702 else if(iterator->length > block->length) {
703 if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) {
704 ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last);
705 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
706 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
707 return ret;
708 }
709 else {
710 if((ret = rewrite_whole_file_(iterator, block, /*append=*/false))) {
711 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
712 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
713 }
714 return ret;
715 }
716 }
717 else /* iterator->length < block->length */ {
718 uint32_t padding_leftover = 0;
719 FLAC__bool padding_is_last = false;
720 if(use_padding) {
721 /* first see if we can even use padding */
722 if(iterator->is_last) {
723 use_padding = false;
724 }
725 else {
726 const uint32_t extra_padding_bytes_required = block->length - iterator->length;
727 simple_iterator_push_(iterator);
728 if(!FLAC__metadata_simple_iterator_next(iterator)) {
729 (void)simple_iterator_pop_(iterator);
730 return false;
731 }
732 if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
733 use_padding = false;
734 }
735 else {
736 if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) {
737 padding_leftover = 0;
738 block->is_last = iterator->is_last;
739 }
740 else if(iterator->length < extra_padding_bytes_required)
741 use_padding = false;
742 else {
743 padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required;
744 padding_is_last = iterator->is_last;
745 block->is_last = false;
746 }
747 }
748 if(!simple_iterator_pop_(iterator))
749 return false;
750 }
751 }
752 if(use_padding) {
753 if(padding_leftover == 0) {
754 ret = write_metadata_block_stationary_(iterator, block);
755 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
756 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
757 return ret;
758 }
759 else {
760 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
761 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
762 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
763 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
764 return ret;
765 }
766 }
767 else {
768 if((ret = rewrite_whole_file_(iterator, block, /*append=*/false))) {
769 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
770 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
771 }
772 return ret;
773 }
774 }
775 }
776
FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator * iterator,FLAC__StreamMetadata * block,FLAC__bool use_padding)777 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding)
778 {
779 uint32_t padding_leftover = 0;
780 FLAC__bool padding_is_last = false;
781
782 FLAC__ASSERT_DECLARATION(FLAC__off_t debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
783 FLAC__bool ret;
784
785 FLAC__ASSERT(0 != iterator);
786 FLAC__ASSERT(0 != iterator->file);
787 FLAC__ASSERT(0 != block);
788 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
789
790 if(!iterator->is_writable) {
791 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
792 return false;
793 }
794
795 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
796 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
797 return false;
798 }
799
800 block->is_last = iterator->is_last;
801
802 if(use_padding) {
803 /* first see if we can even use padding */
804 if(iterator->is_last) {
805 use_padding = false;
806 }
807 else {
808 simple_iterator_push_(iterator);
809 if(!FLAC__metadata_simple_iterator_next(iterator)) {
810 (void)simple_iterator_pop_(iterator);
811 return false;
812 }
813 if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
814 use_padding = false;
815 }
816 else {
817 if(iterator->length == block->length) {
818 padding_leftover = 0;
819 block->is_last = iterator->is_last;
820 }
821 else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length)
822 use_padding = false;
823 else {
824 padding_leftover = iterator->length - block->length;
825 padding_is_last = iterator->is_last;
826 block->is_last = false;
827 }
828 }
829 if(!simple_iterator_pop_(iterator))
830 return false;
831 }
832 }
833 if(use_padding) {
834 /* move to the next block, which is suitable padding */
835 if(!FLAC__metadata_simple_iterator_next(iterator))
836 return false;
837 if(padding_leftover == 0) {
838 ret = write_metadata_block_stationary_(iterator, block);
839 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
840 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
841 return ret;
842 }
843 else {
844 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
845 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
846 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
847 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
848 return ret;
849 }
850 }
851 else {
852 if((ret = rewrite_whole_file_(iterator, block, /*append=*/true))) {
853 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
854 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
855 }
856 return ret;
857 }
858 }
859
FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator * iterator,FLAC__bool use_padding)860 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding)
861 {
862 FLAC__ASSERT_DECLARATION(FLAC__off_t debug_target_offset = iterator->offset[iterator->depth];)
863 FLAC__bool ret;
864
865 FLAC__ASSERT(iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
866
867 if(!iterator->is_writable) {
868 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
869 return false;
870 }
871
872 if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
873 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
874 return false;
875 }
876
877 if(use_padding) {
878 FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
879 if(0 == padding) {
880 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
881 return false;
882 }
883 padding->length = iterator->length;
884 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) {
885 FLAC__metadata_object_delete(padding);
886 return false;
887 }
888 FLAC__metadata_object_delete(padding);
889 if(!FLAC__metadata_simple_iterator_prev(iterator))
890 return false;
891 FLAC__ASSERT(iterator->offset[iterator->depth] + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (FLAC__off_t)iterator->length == debug_target_offset);
892 FLAC__ASSERT(ftello(iterator->file) + (FLAC__off_t)iterator->length == debug_target_offset);
893 return true;
894 }
895 else {
896 if((ret = rewrite_whole_file_(iterator, 0, /*append=*/false))) {
897 FLAC__ASSERT(iterator->offset[iterator->depth] + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (FLAC__off_t)iterator->length == debug_target_offset);
898 FLAC__ASSERT(ftello(iterator->file) + (FLAC__off_t)iterator->length == debug_target_offset);
899 }
900 return ret;
901 }
902 }
903
904
905
906 /****************************************************************************
907 *
908 * Level 2 implementation
909 *
910 ***************************************************************************/
911
912
913 typedef struct FLAC__Metadata_Node {
914 FLAC__StreamMetadata *data;
915 struct FLAC__Metadata_Node *prev, *next;
916 } FLAC__Metadata_Node;
917
918 struct FLAC__Metadata_Chain {
919 char *filename; /* will be NULL if using callbacks */
920 FLAC__bool is_ogg;
921 FLAC__Metadata_Node *head;
922 FLAC__Metadata_Node *tail;
923 uint32_t nodes;
924 FLAC__Metadata_ChainStatus status;
925 FLAC__off_t first_offset, last_offset;
926 /*
927 * This is the length of the chain initially read from the FLAC file.
928 * it is used to compare against the current length to decide whether
929 * or not the whole file has to be rewritten.
930 */
931 FLAC__off_t initial_length;
932 /* @@@ hacky, these are currently only needed by ogg reader */
933 FLAC__IOHandle handle;
934 FLAC__IOCallback_Read read_cb;
935 };
936
937 struct FLAC__Metadata_Iterator {
938 FLAC__Metadata_Chain *chain;
939 FLAC__Metadata_Node *current;
940 };
941
942 FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = {
943 "FLAC__METADATA_CHAIN_STATUS_OK",
944 "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT",
945 "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE",
946 "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE",
947 "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE",
948 "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA",
949 "FLAC__METADATA_CHAIN_STATUS_READ_ERROR",
950 "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR",
951 "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR",
952 "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
953 "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
954 "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
955 "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR",
956 "FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS",
957 "FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH",
958 "FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL"
959 };
960
961
node_new_(void)962 static FLAC__Metadata_Node *node_new_(void)
963 {
964 return calloc(1, sizeof(FLAC__Metadata_Node));
965 }
966
node_delete_(FLAC__Metadata_Node * node)967 static void node_delete_(FLAC__Metadata_Node *node)
968 {
969 FLAC__ASSERT(0 != node);
970 if(0 != node->data)
971 FLAC__metadata_object_delete(node->data);
972 free(node);
973 }
974
chain_init_(FLAC__Metadata_Chain * chain)975 static void chain_init_(FLAC__Metadata_Chain *chain)
976 {
977 FLAC__ASSERT(0 != chain);
978
979 chain->filename = 0;
980 chain->is_ogg = false;
981 chain->head = chain->tail = 0;
982 chain->nodes = 0;
983 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
984 chain->initial_length = 0;
985 chain->read_cb = 0;
986 }
987
chain_clear_(FLAC__Metadata_Chain * chain)988 static void chain_clear_(FLAC__Metadata_Chain *chain)
989 {
990 FLAC__Metadata_Node *node, *next;
991
992 FLAC__ASSERT(0 != chain);
993
994 for(node = chain->head; node; ) {
995 next = node->next;
996 node_delete_(node);
997 node = next;
998 }
999
1000 if(0 != chain->filename)
1001 free(chain->filename);
1002
1003 chain_init_(chain);
1004 }
1005
chain_append_node_(FLAC__Metadata_Chain * chain,FLAC__Metadata_Node * node)1006 static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
1007 {
1008 FLAC__ASSERT(0 != chain);
1009 FLAC__ASSERT(0 != node);
1010 FLAC__ASSERT(0 != node->data);
1011
1012 node->next = node->prev = 0;
1013 node->data->is_last = true;
1014 if(0 != chain->tail)
1015 chain->tail->data->is_last = false;
1016
1017 if(0 == chain->head)
1018 chain->head = node;
1019 else {
1020 FLAC__ASSERT(0 != chain->tail);
1021 chain->tail->next = node;
1022 node->prev = chain->tail;
1023 }
1024 chain->tail = node;
1025 chain->nodes++;
1026 }
1027
chain_remove_node_(FLAC__Metadata_Chain * chain,FLAC__Metadata_Node * node)1028 static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
1029 {
1030 FLAC__ASSERT(0 != chain);
1031 FLAC__ASSERT(0 != node);
1032
1033 if(node == chain->head)
1034 chain->head = node->next;
1035 else
1036 node->prev->next = node->next;
1037
1038 if(node == chain->tail)
1039 chain->tail = node->prev;
1040 else
1041 node->next->prev = node->prev;
1042
1043 if(0 != chain->tail)
1044 chain->tail->data->is_last = true;
1045
1046 chain->nodes--;
1047 }
1048
chain_delete_node_(FLAC__Metadata_Chain * chain,FLAC__Metadata_Node * node)1049 static void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
1050 {
1051 chain_remove_node_(chain, node);
1052 node_delete_(node);
1053 }
1054
chain_calculate_length_(FLAC__Metadata_Chain * chain)1055 static FLAC__off_t chain_calculate_length_(FLAC__Metadata_Chain *chain)
1056 {
1057 const FLAC__Metadata_Node *node;
1058 FLAC__off_t length = 0;
1059 for(node = chain->head; node; node = node->next)
1060 length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1061 return length;
1062 }
1063
iterator_insert_node_(FLAC__Metadata_Iterator * iterator,FLAC__Metadata_Node * node)1064 static void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
1065 {
1066 FLAC__ASSERT(0 != node);
1067 FLAC__ASSERT(0 != node->data);
1068 FLAC__ASSERT(0 != iterator);
1069 FLAC__ASSERT(0 != iterator->current);
1070 FLAC__ASSERT(0 != iterator->chain);
1071 FLAC__ASSERT(0 != iterator->chain->head);
1072 FLAC__ASSERT(0 != iterator->chain->tail);
1073
1074 node->data->is_last = false;
1075
1076 node->prev = iterator->current->prev;
1077 node->next = iterator->current;
1078
1079 if(0 == node->prev)
1080 iterator->chain->head = node;
1081 else
1082 node->prev->next = node;
1083
1084 iterator->current->prev = node;
1085
1086 iterator->chain->nodes++;
1087 }
1088
iterator_insert_node_after_(FLAC__Metadata_Iterator * iterator,FLAC__Metadata_Node * node)1089 static void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
1090 {
1091 FLAC__ASSERT(0 != node);
1092 FLAC__ASSERT(0 != node->data);
1093 FLAC__ASSERT(0 != iterator);
1094 FLAC__ASSERT(0 != iterator->current);
1095 FLAC__ASSERT(0 != iterator->chain);
1096 FLAC__ASSERT(0 != iterator->chain->head);
1097 FLAC__ASSERT(0 != iterator->chain->tail);
1098
1099 iterator->current->data->is_last = false;
1100
1101 node->prev = iterator->current;
1102 node->next = iterator->current->next;
1103
1104 if(0 == node->next)
1105 iterator->chain->tail = node;
1106 else
1107 node->next->prev = node;
1108
1109 node->prev->next = node;
1110
1111 iterator->chain->tail->data->is_last = true;
1112
1113 iterator->chain->nodes++;
1114 }
1115
1116 /* return true iff node and node->next are both padding */
chain_merge_adjacent_padding_(FLAC__Metadata_Chain * chain,FLAC__Metadata_Node * node)1117 static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
1118 {
1119 if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) {
1120 const uint32_t growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length;
1121 node->data->length += growth; /* new block size can be greater than max metadata block size, but it'll be fixed later in chain_prepare_for_write_() */
1122
1123 chain_delete_node_(chain, node->next);
1124 return true;
1125 }
1126 else
1127 return false;
1128 }
1129
1130 #if defined(_MSC_VER)
1131 // silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data'
1132 #pragma warning ( disable : 4244 )
1133 #endif
1134
1135 /* Returns the new length of the chain, or 0 if there was an error. */
1136 /* WATCHOUT: This can get called multiple times before a write, so
1137 * it should still work when this happens.
1138 */
1139 /* WATCHOUT: Make sure to also update the logic in
1140 * FLAC__metadata_chain_check_if_tempfile_needed() if the logic here changes.
1141 */
chain_prepare_for_write_(FLAC__Metadata_Chain * chain,FLAC__bool use_padding)1142 static FLAC__off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
1143 {
1144 FLAC__off_t current_length = chain_calculate_length_(chain);
1145 FLAC__Metadata_Node * i;
1146
1147 /* Check all is_last settings on the blocks */
1148 for(i = chain->head; i->next != NULL; i = i->next)
1149 i->data->is_last = 0;
1150 chain->tail->data->is_last = 1;
1151
1152 if(use_padding) {
1153 /* if the metadata shrank and the last block is padding, we just extend the last padding block */
1154 if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1155 const FLAC__off_t delta = chain->initial_length - current_length;
1156 chain->tail->data->length += delta;
1157 current_length += delta;
1158 FLAC__ASSERT(current_length == chain->initial_length);
1159 }
1160 /* if the metadata shrank more than 4 bytes then there's room to add another padding block */
1161 else if(current_length + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
1162 FLAC__StreamMetadata *padding;
1163 FLAC__Metadata_Node *node;
1164 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
1165 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1166 return 0;
1167 }
1168 padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + current_length);
1169 if(0 == (node = node_new_())) {
1170 FLAC__metadata_object_delete(padding);
1171 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1172 return 0;
1173 }
1174 node->data = padding;
1175 chain_append_node_(chain, node);
1176 current_length = chain_calculate_length_(chain);
1177 FLAC__ASSERT(current_length == chain->initial_length);
1178 }
1179 /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */
1180 else if(current_length > chain->initial_length) {
1181 const FLAC__off_t delta = current_length - chain->initial_length;
1182 if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1183 /* if the delta is exactly the size of the last padding block, remove the padding block */
1184 if((FLAC__off_t)chain->tail->data->length + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
1185 chain_delete_node_(chain, chain->tail);
1186 current_length = chain_calculate_length_(chain);
1187 FLAC__ASSERT(current_length == chain->initial_length);
1188 }
1189 /* if there is at least 'delta' bytes of padding, trim the padding down */
1190 else if((FLAC__off_t)chain->tail->data->length >= delta) {
1191 chain->tail->data->length -= delta;
1192 current_length -= delta;
1193 FLAC__ASSERT(current_length == chain->initial_length);
1194 }
1195 }
1196 }
1197 }
1198
1199 /* check sizes of all metadata blocks; reduce padding size if necessary */
1200 {
1201 FLAC__Metadata_Node *node;
1202 for (node = chain->head; node; node = node->next) {
1203 if(node->data->length >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) {
1204 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1205 node->data->length = (1u << FLAC__STREAM_METADATA_LENGTH_LEN) - 1;
1206 current_length = chain_calculate_length_(chain);
1207 } else {
1208 chain->status = FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
1209 return 0;
1210 }
1211 }
1212 }
1213 }
1214
1215 return current_length;
1216 }
1217
1218 #if defined(_MSC_VER)
1219 #pragma warning ( default : 4244 )
1220 #endif
1221
chain_read_cb_(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Seek seek_cb,FLAC__IOCallback_Tell tell_cb)1222 static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb)
1223 {
1224 FLAC__Metadata_Node *node;
1225
1226 FLAC__ASSERT(0 != chain);
1227
1228 /* we assume we're already at the beginning of the file */
1229
1230 switch(seek_to_first_metadata_block_cb_(handle, read_cb, seek_cb)) {
1231 case 0:
1232 break;
1233 case 1:
1234 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1235 return false;
1236 case 2:
1237 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1238 return false;
1239 case 3:
1240 chain->status = FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
1241 return false;
1242 default:
1243 FLAC__ASSERT(0);
1244 return false;
1245 }
1246
1247 {
1248 FLAC__int64 pos = tell_cb(handle);
1249 if(pos < 0) {
1250 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1251 return false;
1252 }
1253 chain->first_offset = (FLAC__off_t)pos;
1254 }
1255
1256 {
1257 FLAC__bool is_last;
1258 FLAC__MetadataType type;
1259 uint32_t length;
1260
1261 do {
1262 node = node_new_();
1263 if(0 == node) {
1264 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1265 return false;
1266 }
1267
1268 if(!read_metadata_block_header_cb_(handle, read_cb, &is_last, &type, &length)) {
1269 node_delete_(node);
1270 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1271 return false;
1272 }
1273
1274 node->data = FLAC__metadata_object_new(type);
1275 if(0 == node->data) {
1276 node_delete_(node);
1277 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1278 return false;
1279 }
1280
1281 node->data->is_last = is_last;
1282 node->data->length = length;
1283
1284 chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data));
1285 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) {
1286 node_delete_(node);
1287 return false;
1288 }
1289 chain_append_node_(chain, node);
1290 } while(!is_last);
1291 }
1292
1293 {
1294 FLAC__int64 pos = tell_cb(handle);
1295 if(pos < 0) {
1296 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1297 return false;
1298 }
1299 chain->last_offset = (FLAC__off_t)pos;
1300 }
1301
1302 if(chain->head->data->type != FLAC__METADATA_TYPE_STREAMINFO) {
1303 chain->status = FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
1304 return false;
1305 }
1306
1307 chain->initial_length = chain_calculate_length_(chain);
1308
1309 return true;
1310 }
1311
chain_read_ogg_read_cb_(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * client_data)1312 static FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
1313 {
1314 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1315 (void)decoder;
1316 if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) {
1317 *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle);
1318 if(*bytes == 0)
1319 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
1320 else
1321 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
1322 }
1323 else
1324 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
1325 }
1326
chain_read_ogg_write_cb_(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)1327 static FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
1328 {
1329 (void)decoder, (void)frame, (void)buffer, (void)client_data;
1330 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
1331 }
1332
chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)1333 static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
1334 {
1335 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1336 FLAC__Metadata_Node *node;
1337
1338 (void)decoder;
1339
1340 node = node_new_();
1341 if(0 == node) {
1342 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1343 return;
1344 }
1345
1346 node->data = FLAC__metadata_object_clone(metadata);
1347 if(0 == node->data) {
1348 node_delete_(node);
1349 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1350 return;
1351 }
1352
1353 chain_append_node_(chain, node);
1354 }
1355
chain_read_ogg_error_cb_(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)1356 static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
1357 {
1358 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1359 (void)decoder, (void)status;
1360 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1361 }
1362
chain_read_ogg_cb_(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb)1363 static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb)
1364 {
1365 FLAC__StreamDecoder *decoder;
1366
1367 FLAC__ASSERT(0 != chain);
1368
1369 /* we assume we're already at the beginning of the file */
1370
1371 chain->handle = handle;
1372 chain->read_cb = read_cb;
1373 if(0 == (decoder = FLAC__stream_decoder_new())) {
1374 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1375 return false;
1376 }
1377 FLAC__stream_decoder_set_metadata_respond_all(decoder);
1378 if(FLAC__stream_decoder_init_ogg_stream(decoder, chain_read_ogg_read_cb_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, chain_read_ogg_write_cb_, chain_read_ogg_metadata_cb_, chain_read_ogg_error_cb_, chain) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
1379 FLAC__stream_decoder_delete(decoder);
1380 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1381 return false;
1382 }
1383
1384 chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
1385
1386 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
1387 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1388 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) {
1389 FLAC__stream_decoder_delete(decoder);
1390 return false;
1391 }
1392
1393 FLAC__stream_decoder_delete(decoder);
1394
1395 chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
1396
1397 chain->initial_length = chain_calculate_length_(chain);
1398
1399 if(chain->initial_length == 0 || chain->head->data->type != FLAC__METADATA_TYPE_STREAMINFO) {
1400 /* Ogg FLAC file must have at least streaminfo and vorbis comment */
1401 chain->status = FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
1402 return false;
1403 }
1404
1405 return true;
1406 }
1407
chain_rewrite_metadata_in_place_cb_(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,FLAC__IOCallback_Seek seek_cb)1408 static FLAC__bool chain_rewrite_metadata_in_place_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, FLAC__IOCallback_Seek seek_cb)
1409 {
1410 FLAC__Metadata_Node *node;
1411
1412 FLAC__ASSERT(0 != chain);
1413 FLAC__ASSERT(0 != chain->head);
1414
1415 if(0 != seek_cb(handle, chain->first_offset, SEEK_SET)) {
1416 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1417 return false;
1418 }
1419
1420 for(node = chain->head; node; node = node->next) {
1421 if(!write_metadata_block_header_cb_(handle, write_cb, node->data)) {
1422 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
1423 return false;
1424 }
1425 if(!write_metadata_block_data_cb_(handle, write_cb, node->data)) {
1426 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
1427 return false;
1428 }
1429 }
1430
1431 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1432
1433 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
1434 return true;
1435 }
1436
chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain * chain)1437 static FLAC__bool chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain *chain)
1438 {
1439 FILE *file;
1440 FLAC__bool ret;
1441
1442 FLAC__ASSERT(0 != chain->filename);
1443
1444 if(0 == (file = flac_fopen(chain->filename, "r+b"))) {
1445 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1446 return false;
1447 }
1448
1449 /* chain_rewrite_metadata_in_place_cb_() sets chain->status for us */
1450 ret = chain_rewrite_metadata_in_place_cb_(chain, (FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, fseek_wrapper_);
1451
1452 fclose(file);
1453
1454 return ret;
1455 }
1456
chain_rewrite_file_(FLAC__Metadata_Chain * chain,const char * tempfile_path_prefix)1457 static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix)
1458 {
1459 FILE *f, *tempfile = NULL;
1460 char *tempfilename;
1461 FLAC__Metadata_SimpleIteratorStatus status;
1462 const FLAC__Metadata_Node *node;
1463
1464 FLAC__ASSERT(0 != chain);
1465 FLAC__ASSERT(0 != chain->filename);
1466 FLAC__ASSERT(0 != chain->head);
1467
1468 /* copy the file prefix (data up to first metadata block */
1469 if(0 == (f = flac_fopen(chain->filename, "rb"))) {
1470 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1471 return false;
1472 }
1473 if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) {
1474 chain->status = get_equivalent_status_(status);
1475 goto err;
1476 }
1477 if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) {
1478 chain->status = get_equivalent_status_(status);
1479 goto err;
1480 }
1481
1482 /* write the metadata */
1483 for(node = chain->head; node; node = node->next) {
1484 if(!write_metadata_block_header_(tempfile, &status, node->data)) {
1485 chain->status = get_equivalent_status_(status);
1486 goto err;
1487 }
1488 if(!write_metadata_block_data_(tempfile, &status, node->data)) {
1489 chain->status = get_equivalent_status_(status);
1490 goto err;
1491 }
1492 }
1493 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1494
1495 /* copy the file postfix (everything after the metadata) */
1496 if(0 != fseeko(f, chain->last_offset, SEEK_SET)) {
1497 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1498 goto err;
1499 }
1500 if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) {
1501 chain->status = get_equivalent_status_(status);
1502 goto err;
1503 }
1504
1505 /* move the tempfile on top of the original */
1506 (void)fclose(f);
1507 if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
1508 return false;
1509
1510 return true;
1511
1512 err:
1513 (void)fclose(f);
1514 cleanup_tempfile_(&tempfile, &tempfilename);
1515 return false;
1516 }
1517
1518 /* assumes 'handle' is already at beginning of file */
chain_rewrite_file_cb_(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Seek seek_cb,FLAC__IOCallback_Eof eof_cb,FLAC__IOHandle temp_handle,FLAC__IOCallback_Write temp_write_cb)1519 static FLAC__bool chain_rewrite_file_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb)
1520 {
1521 FLAC__Metadata_SimpleIteratorStatus status;
1522 const FLAC__Metadata_Node *node;
1523
1524 FLAC__ASSERT(0 != chain);
1525 FLAC__ASSERT(0 == chain->filename);
1526 FLAC__ASSERT(0 != chain->head);
1527
1528 /* copy the file prefix (data up to first metadata block */
1529 if(!copy_n_bytes_from_file_cb_(handle, read_cb, temp_handle, temp_write_cb, chain->first_offset, &status)) {
1530 chain->status = get_equivalent_status_(status);
1531 return false;
1532 }
1533
1534 /* write the metadata */
1535 for(node = chain->head; node; node = node->next) {
1536 if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) {
1537 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
1538 return false;
1539 }
1540 if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) {
1541 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
1542 return false;
1543 }
1544 }
1545 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1546
1547 /* copy the file postfix (everything after the metadata) */
1548 if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) {
1549 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1550 return false;
1551 }
1552 if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) {
1553 chain->status = get_equivalent_status_(status);
1554 return false;
1555 }
1556
1557 return true;
1558 }
1559
FLAC__metadata_chain_new(void)1560 FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void)
1561 {
1562 FLAC__Metadata_Chain *chain = calloc(1, sizeof(FLAC__Metadata_Chain));
1563
1564 if(0 != chain)
1565 chain_init_(chain);
1566
1567 return chain;
1568 }
1569
FLAC__metadata_chain_delete(FLAC__Metadata_Chain * chain)1570 FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain)
1571 {
1572 FLAC__ASSERT(0 != chain);
1573
1574 chain_clear_(chain);
1575
1576 free(chain);
1577 }
1578
FLAC__metadata_chain_status(FLAC__Metadata_Chain * chain)1579 FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain)
1580 {
1581 FLAC__Metadata_ChainStatus status;
1582
1583 FLAC__ASSERT(0 != chain);
1584
1585 status = chain->status;
1586 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
1587 return status;
1588 }
1589
chain_read_(FLAC__Metadata_Chain * chain,const char * filename,FLAC__bool is_ogg)1590 static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg)
1591 {
1592 FILE *file;
1593 FLAC__bool ret;
1594
1595 FLAC__ASSERT(0 != chain);
1596 FLAC__ASSERT(0 != filename);
1597
1598 chain_clear_(chain);
1599
1600 if(0 == (chain->filename = strdup(filename))) {
1601 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1602 return false;
1603 }
1604
1605 chain->is_ogg = is_ogg;
1606
1607 if(0 == (file = flac_fopen(filename, "rb"))) {
1608 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1609 return false;
1610 }
1611
1612 /* the function also sets chain->status for us */
1613 ret = is_ogg?
1614 chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) :
1615 chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_)
1616 ;
1617
1618 fclose(file);
1619
1620 return ret;
1621 }
1622
FLAC__metadata_chain_read(FLAC__Metadata_Chain * chain,const char * filename)1623 FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
1624 {
1625 return chain_read_(chain, filename, /*is_ogg=*/false);
1626 }
1627
1628 /*@@@@add to tests*/
FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain * chain,const char * filename)1629 FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename)
1630 {
1631 return chain_read_(chain, filename, /*is_ogg=*/true);
1632 }
1633
chain_read_with_callbacks_(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallbacks callbacks,FLAC__bool is_ogg)1634 static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg)
1635 {
1636 FLAC__bool ret;
1637
1638 FLAC__ASSERT(0 != chain);
1639
1640 chain_clear_(chain);
1641
1642 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
1643 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1644 return false;
1645 }
1646
1647 chain->is_ogg = is_ogg;
1648
1649 /* rewind */
1650 if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
1651 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1652 return false;
1653 }
1654
1655 /* the function also sets chain->status for us */
1656 ret = is_ogg?
1657 chain_read_ogg_cb_(chain, handle, callbacks.read) :
1658 chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell)
1659 ;
1660
1661 return ret;
1662 }
1663
FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallbacks callbacks)1664 FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1665 {
1666 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false);
1667 }
1668
1669 /*@@@@add to tests*/
FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain * chain,FLAC__IOHandle handle,FLAC__IOCallbacks callbacks)1670 FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1671 {
1672 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true);
1673 }
1674
1675 typedef enum {
1676 LBS_NONE = 0,
1677 LBS_SIZE_CHANGED,
1678 LBS_BLOCK_ADDED,
1679 LBS_BLOCK_REMOVED
1680 } LastBlockState;
1681
1682 #if defined(_MSC_VER)
1683 // silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data'
1684 #pragma warning ( disable : 4244 )
1685 #endif
1686
FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain * chain,FLAC__bool use_padding)1687 FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
1688 {
1689 /* This does all the same checks that are in chain_prepare_for_write_()
1690 * but doesn't actually alter the chain. Make sure to update the logic
1691 * here if chain_prepare_for_write_() changes.
1692 */
1693 FLAC__off_t current_length;
1694 LastBlockState lbs_state = LBS_NONE;
1695 uint32_t lbs_size = 0;
1696
1697 FLAC__ASSERT(0 != chain);
1698
1699 current_length = chain_calculate_length_(chain);
1700
1701 if(use_padding) {
1702 const FLAC__Metadata_Node * const node = chain->tail;
1703 /* if the metadata shrank and the last block is padding, we just extend the last padding block */
1704 if(current_length < chain->initial_length && node->data->type == FLAC__METADATA_TYPE_PADDING) {
1705 lbs_state = LBS_SIZE_CHANGED;
1706 lbs_size = node->data->length + (chain->initial_length - current_length);
1707 }
1708 /* if the metadata shrank more than 4 bytes then there's room to add another padding block */
1709 else if(current_length + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
1710 lbs_state = LBS_BLOCK_ADDED;
1711 lbs_size = chain->initial_length - (current_length + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
1712 }
1713 /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */
1714 else if(current_length > chain->initial_length) {
1715 const FLAC__off_t delta = current_length - chain->initial_length;
1716 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1717 /* if the delta is exactly the size of the last padding block, remove the padding block */
1718 if((FLAC__off_t)node->data->length + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
1719 lbs_state = LBS_BLOCK_REMOVED;
1720 lbs_size = 0;
1721 }
1722 /* if there is at least 'delta' bytes of padding, trim the padding down */
1723 else if((FLAC__off_t)node->data->length >= delta) {
1724 lbs_state = LBS_SIZE_CHANGED;
1725 lbs_size = node->data->length - delta;
1726 }
1727 }
1728 }
1729 }
1730
1731 current_length = 0;
1732 /* check sizes of all metadata blocks; reduce padding size if necessary */
1733 {
1734 const FLAC__Metadata_Node *node;
1735 for(node = chain->head; node; node = node->next) {
1736 uint32_t block_len = node->data->length;
1737 if(node == chain->tail) {
1738 if(lbs_state == LBS_BLOCK_REMOVED)
1739 continue;
1740 else if(lbs_state == LBS_SIZE_CHANGED)
1741 block_len = lbs_size;
1742 }
1743 if(block_len >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) {
1744 if(node->data->type == FLAC__METADATA_TYPE_PADDING)
1745 block_len = (1u << FLAC__STREAM_METADATA_LENGTH_LEN) - 1;
1746 else
1747 return false /* the return value doesn't matter */;
1748 }
1749 current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + block_len);
1750 }
1751
1752 if(lbs_state == LBS_BLOCK_ADDED) {
1753 /* test added padding block */
1754 uint32_t block_len = lbs_size;
1755 if(block_len >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
1756 block_len = (1u << FLAC__STREAM_METADATA_LENGTH_LEN) - 1;
1757 current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + block_len);
1758 }
1759 }
1760
1761 return (current_length != chain->initial_length);
1762 }
1763
1764 #if defined(_MSC_VER)
1765 #pragma warning ( default : 4244 )
1766 #endif
1767
FLAC__metadata_chain_write(FLAC__Metadata_Chain * chain,FLAC__bool use_padding,FLAC__bool preserve_file_stats)1768 FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
1769 {
1770 struct flac_stat_s stats;
1771 const char *tempfile_path_prefix = 0;
1772 FLAC__off_t current_length;
1773
1774 FLAC__ASSERT(0 != chain);
1775
1776 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
1777 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
1778 return false;
1779 }
1780
1781 if (0 == chain->filename) {
1782 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1783 return false;
1784 }
1785
1786 current_length = chain_prepare_for_write_(chain, use_padding);
1787
1788 /* a return value of 0 means there was an error; chain->status is already set */
1789 if (0 == current_length)
1790 return false;
1791
1792 if(preserve_file_stats)
1793 get_file_stats_(chain->filename, &stats);
1794
1795 if(current_length == chain->initial_length) {
1796 if(!chain_rewrite_metadata_in_place_(chain))
1797 return false;
1798 }
1799 else {
1800 if(!chain_rewrite_file_(chain, tempfile_path_prefix))
1801 return false;
1802
1803 /* recompute lengths and offsets */
1804 {
1805 const FLAC__Metadata_Node *node;
1806 chain->initial_length = current_length;
1807 chain->last_offset = chain->first_offset;
1808 for(node = chain->head; node; node = node->next)
1809 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1810 }
1811 }
1812
1813 if(preserve_file_stats)
1814 set_file_stats_(chain->filename, &stats);
1815
1816 return true;
1817 }
1818
FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain * chain,FLAC__bool use_padding,FLAC__IOHandle handle,FLAC__IOCallbacks callbacks)1819 FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1820 {
1821 FLAC__off_t current_length;
1822
1823 FLAC__ASSERT(0 != chain);
1824
1825 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
1826 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
1827 return false;
1828 }
1829
1830 if (0 != chain->filename) {
1831 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1832 return false;
1833 }
1834
1835 if (0 == callbacks.write || 0 == callbacks.seek) {
1836 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1837 return false;
1838 }
1839
1840 if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
1841 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL;
1842 return false;
1843 }
1844
1845 current_length = chain_prepare_for_write_(chain, use_padding);
1846
1847 /* a return value of 0 means there was an error; chain->status is already set */
1848 if (0 == current_length)
1849 return false;
1850
1851 FLAC__ASSERT(current_length == chain->initial_length);
1852
1853 return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek);
1854 }
1855
FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain * chain,FLAC__bool use_padding,FLAC__IOHandle handle,FLAC__IOCallbacks callbacks,FLAC__IOHandle temp_handle,FLAC__IOCallbacks temp_callbacks)1856 FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks)
1857 {
1858 FLAC__off_t current_length;
1859
1860 FLAC__ASSERT(0 != chain);
1861
1862 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
1863 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
1864 return false;
1865 }
1866
1867 if (0 != chain->filename) {
1868 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1869 return false;
1870 }
1871
1872 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) {
1873 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1874 return false;
1875 }
1876 if (0 == temp_callbacks.write) {
1877 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1878 return false;
1879 }
1880
1881 if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
1882 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL;
1883 return false;
1884 }
1885
1886 current_length = chain_prepare_for_write_(chain, use_padding);
1887
1888 /* a return value of 0 means there was an error; chain->status is already set */
1889 if (0 == current_length)
1890 return false;
1891
1892 FLAC__ASSERT(current_length != chain->initial_length);
1893
1894 /* rewind */
1895 if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
1896 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1897 return false;
1898 }
1899
1900 if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write))
1901 return false;
1902
1903 /* recompute lengths and offsets */
1904 {
1905 const FLAC__Metadata_Node *node;
1906 chain->initial_length = current_length;
1907 chain->last_offset = chain->first_offset;
1908 for(node = chain->head; node; node = node->next)
1909 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1910 }
1911
1912 return true;
1913 }
1914
FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain * chain)1915 FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain)
1916 {
1917 FLAC__Metadata_Node *node;
1918
1919 FLAC__ASSERT(0 != chain);
1920
1921 for(node = chain->head; node; ) {
1922 if(!chain_merge_adjacent_padding_(chain, node))
1923 node = node->next;
1924 }
1925 }
1926
FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain * chain)1927 FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain)
1928 {
1929 FLAC__Metadata_Node *node, *save;
1930 uint32_t i;
1931
1932 FLAC__ASSERT(0 != chain);
1933
1934 /*
1935 * Don't try and be too smart... this simple algo is good enough for
1936 * the small number of nodes that we deal with.
1937 */
1938 for(i = 0, node = chain->head; i < chain->nodes; i++) {
1939 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1940 save = node->next;
1941 chain_remove_node_(chain, node);
1942 chain_append_node_(chain, node);
1943 node = save;
1944 }
1945 else {
1946 node = node->next;
1947 }
1948 }
1949
1950 FLAC__metadata_chain_merge_padding(chain);
1951 }
1952
1953
FLAC__metadata_iterator_new(void)1954 FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void)
1955 {
1956 FLAC__Metadata_Iterator *iterator = calloc(1, sizeof(FLAC__Metadata_Iterator));
1957
1958 /* calloc() implies:
1959 iterator->current = 0;
1960 iterator->chain = 0;
1961 */
1962
1963 return iterator;
1964 }
1965
FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator * iterator)1966 FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator)
1967 {
1968 FLAC__ASSERT(0 != iterator);
1969
1970 free(iterator);
1971 }
1972
FLAC__metadata_iterator_init(FLAC__Metadata_Iterator * iterator,FLAC__Metadata_Chain * chain)1973 FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain)
1974 {
1975 FLAC__ASSERT(0 != iterator);
1976 FLAC__ASSERT(0 != chain);
1977 FLAC__ASSERT(0 != chain->head);
1978
1979 iterator->chain = chain;
1980 iterator->current = chain->head;
1981 }
1982
FLAC__metadata_iterator_next(FLAC__Metadata_Iterator * iterator)1983 FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator)
1984 {
1985 FLAC__ASSERT(0 != iterator);
1986
1987 if(0 == iterator->current || 0 == iterator->current->next)
1988 return false;
1989
1990 iterator->current = iterator->current->next;
1991 return true;
1992 }
1993
FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator * iterator)1994 FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator)
1995 {
1996 FLAC__ASSERT(0 != iterator);
1997
1998 if(0 == iterator->current || 0 == iterator->current->prev)
1999 return false;
2000
2001 iterator->current = iterator->current->prev;
2002 return true;
2003 }
2004
FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator * iterator)2005 FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator)
2006 {
2007 FLAC__ASSERT(0 != iterator);
2008 FLAC__ASSERT(0 != iterator->current);
2009 FLAC__ASSERT(0 != iterator->current->data);
2010
2011 return iterator->current->data->type;
2012 }
2013
FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator * iterator)2014 FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator)
2015 {
2016 FLAC__ASSERT(0 != iterator);
2017 FLAC__ASSERT(0 != iterator->current);
2018
2019 return iterator->current->data;
2020 }
2021
FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator * iterator,FLAC__StreamMetadata * block)2022 FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
2023 {
2024 FLAC__ASSERT(0 != iterator);
2025 FLAC__ASSERT(0 != block);
2026 return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
2027 }
2028
FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator * iterator,FLAC__bool replace_with_padding)2029 FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding)
2030 {
2031 FLAC__Metadata_Node *save;
2032
2033 FLAC__ASSERT(0 != iterator);
2034 FLAC__ASSERT(0 != iterator->current);
2035
2036 if(0 == iterator->current->prev) {
2037 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
2038 return false;
2039 }
2040
2041 save = iterator->current->prev;
2042
2043 if(replace_with_padding) {
2044 FLAC__metadata_object_delete_data(iterator->current->data);
2045 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
2046 }
2047 else {
2048 chain_delete_node_(iterator->chain, iterator->current);
2049 }
2050
2051 iterator->current = save;
2052 return true;
2053 }
2054
FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator * iterator,FLAC__StreamMetadata * block)2055 FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
2056 {
2057 FLAC__Metadata_Node *node;
2058
2059 FLAC__ASSERT(0 != iterator);
2060 FLAC__ASSERT(0 != iterator->current);
2061 FLAC__ASSERT(0 != block);
2062
2063 if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
2064 return false;
2065
2066 if(0 == iterator->current->prev) {
2067 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
2068 return false;
2069 }
2070
2071 if(0 == (node = node_new_()))
2072 return false;
2073
2074 node->data = block;
2075 iterator_insert_node_(iterator, node);
2076 iterator->current = node;
2077 return true;
2078 }
2079
FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator * iterator,FLAC__StreamMetadata * block)2080 FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
2081 {
2082 FLAC__Metadata_Node *node;
2083
2084 FLAC__ASSERT(0 != iterator);
2085 FLAC__ASSERT(0 != iterator->current);
2086 FLAC__ASSERT(0 != block);
2087
2088 if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
2089 return false;
2090
2091 if(0 == (node = node_new_()))
2092 return false;
2093
2094 node->data = block;
2095 iterator_insert_node_after_(iterator, node);
2096 iterator->current = node;
2097 return true;
2098 }
2099
2100
2101 /****************************************************************************
2102 *
2103 * Local function definitions
2104 *
2105 ***************************************************************************/
2106
pack_uint32_(FLAC__uint32 val,FLAC__byte * b,uint32_t bytes)2107 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, uint32_t bytes)
2108 {
2109 uint32_t i;
2110
2111 b += bytes;
2112
2113 for(i = 0; i < bytes; i++) {
2114 *(--b) = (FLAC__byte)(val & 0xff);
2115 val >>= 8;
2116 }
2117 }
2118
pack_uint32_little_endian_(FLAC__uint32 val,FLAC__byte * b,uint32_t bytes)2119 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, uint32_t bytes)
2120 {
2121 uint32_t i;
2122
2123 for(i = 0; i < bytes; i++) {
2124 *(b++) = (FLAC__byte)(val & 0xff);
2125 val >>= 8;
2126 }
2127 }
2128
pack_uint64_(FLAC__uint64 val,FLAC__byte * b,uint32_t bytes)2129 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, uint32_t bytes)
2130 {
2131 uint32_t i;
2132
2133 b += bytes;
2134
2135 for(i = 0; i < bytes; i++) {
2136 *(--b) = (FLAC__byte)(val & 0xff);
2137 val >>= 8;
2138 }
2139 }
2140
unpack_uint32_(FLAC__byte * b,uint32_t bytes)2141 FLAC__uint32 unpack_uint32_(FLAC__byte *b, uint32_t bytes)
2142 {
2143 FLAC__uint32 ret = 0;
2144 uint32_t i;
2145
2146 for(i = 0; i < bytes; i++)
2147 ret = (ret << 8) | (FLAC__uint32)(*b++);
2148
2149 return ret;
2150 }
2151
unpack_uint32_little_endian_(FLAC__byte * b,uint32_t bytes)2152 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, uint32_t bytes)
2153 {
2154 FLAC__uint32 ret = 0;
2155 uint32_t i;
2156
2157 b += bytes;
2158
2159 for(i = 0; i < bytes; i++)
2160 ret = (ret << 8) | (FLAC__uint32)(*--b);
2161
2162 return ret;
2163 }
2164
unpack_uint64_(FLAC__byte * b,uint32_t bytes)2165 FLAC__uint64 unpack_uint64_(FLAC__byte *b, uint32_t bytes)
2166 {
2167 FLAC__uint64 ret = 0;
2168 uint32_t i;
2169
2170 for(i = 0; i < bytes; i++)
2171 ret = (ret << 8) | (FLAC__uint64)(*b++);
2172
2173 return ret;
2174 }
2175
read_metadata_block_header_(FLAC__Metadata_SimpleIterator * iterator)2176 FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator)
2177 {
2178 FLAC__ASSERT(0 != iterator);
2179 FLAC__ASSERT(0 != iterator->file);
2180
2181 if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) {
2182 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2183 return false;
2184 }
2185
2186 return true;
2187 }
2188
read_metadata_block_data_(FLAC__Metadata_SimpleIterator * iterator,FLAC__StreamMetadata * block)2189 FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block)
2190 {
2191 FLAC__ASSERT(0 != iterator);
2192 FLAC__ASSERT(0 != iterator->file);
2193
2194 iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block);
2195
2196 return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
2197 }
2198
read_metadata_block_header_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__bool * is_last,FLAC__MetadataType * type,uint32_t * length)2199 FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, uint32_t *length)
2200 {
2201 FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
2202
2203 if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH)
2204 return false;
2205
2206 *is_last = raw_header[0] & 0x80? true : false;
2207 *type = (FLAC__MetadataType)(raw_header[0] & 0x7f);
2208 *length = unpack_uint32_(raw_header + 1, 3);
2209
2210 /* Note that we don't check:
2211 * if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED)
2212 * we just will read in an opaque block
2213 */
2214
2215 return true;
2216 }
2217
read_metadata_block_data_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Seek seek_cb,FLAC__StreamMetadata * block)2218 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block)
2219 {
2220 switch(block->type) {
2221 case FLAC__METADATA_TYPE_STREAMINFO:
2222 return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info);
2223 case FLAC__METADATA_TYPE_PADDING:
2224 return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length);
2225 case FLAC__METADATA_TYPE_APPLICATION:
2226 return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length);
2227 case FLAC__METADATA_TYPE_SEEKTABLE:
2228 return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length);
2229 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
2230 return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, seek_cb, &block->data.vorbis_comment, block->length);
2231 case FLAC__METADATA_TYPE_CUESHEET:
2232 return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet);
2233 case FLAC__METADATA_TYPE_PICTURE:
2234 return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture);
2235 default:
2236 return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length);
2237 }
2238 }
2239
read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_StreamInfo * block)2240 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block)
2241 {
2242 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
2243
2244 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
2245 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2246
2247 b = buffer;
2248
2249 /* we are using hardcoded numbers for simplicity but we should
2250 * probably eventually write a bit-level unpacker and use the
2251 * _STREAMINFO_ constants.
2252 */
2253 block->min_blocksize = unpack_uint32_(b, 2); b += 2;
2254 block->max_blocksize = unpack_uint32_(b, 2); b += 2;
2255 block->min_framesize = unpack_uint32_(b, 3); b += 3;
2256 block->max_framesize = unpack_uint32_(b, 3); b += 3;
2257 block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((uint32_t)(b[2] & 0xf0) >> 4);
2258 block->channels = (uint32_t)((b[2] & 0x0e) >> 1) + 1;
2259 block->bits_per_sample = ((((uint32_t)(b[2] & 0x01)) << 4) | (((uint32_t)(b[3] & 0xf0)) >> 4)) + 1;
2260 block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
2261 memcpy(block->md5sum, b+8, 16);
2262
2263 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2264 }
2265
read_metadata_block_data_padding_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Seek seek_cb,FLAC__StreamMetadata_Padding * block,uint32_t block_length)2266 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, uint32_t block_length)
2267 {
2268 (void)block; /* nothing to do; we don't care about reading the padding bytes */
2269
2270 if(0 != seek_cb(handle, block_length, SEEK_CUR))
2271 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2272
2273 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2274 }
2275
read_metadata_block_data_application_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_Application * block,uint32_t block_length)2276 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, uint32_t block_length)
2277 {
2278 const uint32_t id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
2279
2280 if(read_cb(block->id, 1, id_bytes, handle) != id_bytes)
2281 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2282
2283 if(block_length < id_bytes)
2284 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2285
2286 block_length -= id_bytes;
2287
2288 if(block_length == 0) {
2289 block->data = 0;
2290 }
2291 else {
2292 if(0 == (block->data = malloc(block_length)))
2293 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2294
2295 if(read_cb(block->data, 1, block_length, handle) != block_length)
2296 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2297 }
2298
2299 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2300 }
2301
read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_SeekTable * block,uint32_t block_length)2302 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, uint32_t block_length)
2303 {
2304 uint32_t i;
2305 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
2306
2307 if(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH != 0)
2308 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2309
2310 block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
2311
2312 if(block->num_points == 0)
2313 block->points = 0;
2314 else if(0 == (block->points = safe_malloc_mul_2op_p(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint))))
2315 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2316
2317 for(i = 0; i < block->num_points; i++) {
2318 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
2319 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2320 /* some MAGIC NUMBERs here */
2321 block->points[i].sample_number = unpack_uint64_(buffer, 8);
2322 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
2323 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
2324 }
2325
2326 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2327 }
2328
read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_VorbisComment_Entry * entry,uint32_t max_length)2329 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry, uint32_t max_length)
2330 {
2331 const uint32_t entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
2332 FLAC__byte buffer[4]; /* magic number is asserted below */
2333
2334 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer));
2335
2336 if(max_length < entry_length_len)
2337 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2338
2339 max_length -= entry_length_len;
2340 if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
2341 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2342 entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
2343 if(max_length < entry->length) {
2344 entry->length = 0;
2345 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2346 }
2347
2348 if(0 != entry->entry)
2349 free(entry->entry);
2350
2351 if(0 == (entry->entry = safe_malloc_add_2op_(entry->length, /*+*/1)))
2352 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2353
2354 if(entry->length > 0 && read_cb(entry->entry, 1, entry->length, handle) != entry->length)
2355 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2356
2357 entry->entry[entry->length] = '\0';
2358
2359 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2360 }
2361
read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Seek seek_cb,FLAC__StreamMetadata_VorbisComment * block,uint32_t block_length)2362 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_VorbisComment *block, uint32_t block_length)
2363 {
2364 uint32_t i;
2365 FLAC__Metadata_SimpleIteratorStatus status;
2366 const uint32_t num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2367 FLAC__byte buffer[4]; /* magic number is asserted below */
2368
2369 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer));
2370
2371 status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string), block_length);
2372 if(block_length >= 4)
2373 block_length -= 4;
2374 if(status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA)
2375 goto skip;
2376 else if(status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
2377 return status;
2378 block_length -= block->vendor_string.length;
2379
2380 if(block_length < num_comments_len) goto skip; else block_length -= num_comments_len;
2381 if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len)
2382 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2383 block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
2384
2385 if(block->num_comments == 0) {
2386 block->comments = 0;
2387 }
2388 else if(block->num_comments > (block_length >> 2)) { /* each comment needs at least 4 byte */
2389 block->num_comments = 0;
2390 status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2391 goto skip;
2392 }
2393 else if(0 == (block->comments = calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) {
2394 block->num_comments = 0;
2395 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2396 }
2397
2398 for(i = 0; i < block->num_comments; i++) {
2399 status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i, block_length);
2400 if(block_length >= 4) block_length -= 4;
2401 if(status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA) {
2402 block->num_comments = i;
2403 goto skip;
2404 }
2405 else if(status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) return status;
2406 block_length -= block->comments[i].length;
2407 }
2408
2409 skip:
2410 if(block_length > 0) {
2411 /* bad metadata */
2412 if(0 != seek_cb(handle, block_length, SEEK_CUR))
2413 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2414 }
2415
2416 return status;
2417 }
2418
read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_CueSheet_Track * track)2419 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track)
2420 {
2421 uint32_t i, len;
2422 FLAC__byte buffer[32]; /* asserted below that this is big enough */
2423
2424 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64));
2425 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8);
2426 FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8);
2427
2428 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0);
2429 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8;
2430 if(read_cb(buffer, 1, len, handle) != len)
2431 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2432 track->offset = unpack_uint64_(buffer, len);
2433
2434 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0);
2435 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8;
2436 if(read_cb(buffer, 1, len, handle) != len)
2437 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2438 track->number = (FLAC__byte)unpack_uint32_(buffer, len);
2439
2440 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
2441 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8;
2442 if(read_cb(track->isrc, 1, len, handle) != len)
2443 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2444
2445 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0);
2446 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8;
2447 if(read_cb(buffer, 1, len, handle) != len)
2448 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2449 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1);
2450 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1);
2451 track->type = buffer[0] >> 7;
2452 track->pre_emphasis = (buffer[0] >> 6) & 1;
2453
2454 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0);
2455 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8;
2456 if(read_cb(buffer, 1, len, handle) != len)
2457 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2458 track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len);
2459
2460 if(track->num_indices == 0) {
2461 track->indices = 0;
2462 }
2463 else if(0 == (track->indices = calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index))))
2464 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2465
2466 for(i = 0; i < track->num_indices; i++) {
2467 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0);
2468 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8;
2469 if(read_cb(buffer, 1, len, handle) != len)
2470 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2471 track->indices[i].offset = unpack_uint64_(buffer, len);
2472
2473 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0);
2474 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8;
2475 if(read_cb(buffer, 1, len, handle) != len)
2476 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2477 track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len);
2478
2479 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0);
2480 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8;
2481 if(read_cb(buffer, 1, len, handle) != len)
2482 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2483 }
2484
2485 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2486 }
2487
read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_CueSheet * block)2488 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block)
2489 {
2490 uint32_t i, len;
2491 FLAC__Metadata_SimpleIteratorStatus status;
2492 FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */
2493
2494 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer));
2495 FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer));
2496
2497 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
2498 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8;
2499 if(read_cb(block->media_catalog_number, 1, len, handle) != len)
2500 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2501
2502 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0);
2503 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8;
2504 if(read_cb(buffer, 1, len, handle) != len)
2505 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2506 block->lead_in = unpack_uint64_(buffer, len);
2507
2508 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0);
2509 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8;
2510 if(read_cb(buffer, 1, len, handle) != len)
2511 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2512 block->is_cd = buffer[0]&0x80? true : false;
2513
2514 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0);
2515 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8;
2516 if(read_cb(buffer, 1, len, handle) != len)
2517 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2518 block->num_tracks = unpack_uint32_(buffer, len);
2519
2520 if(block->num_tracks == 0) {
2521 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2522 }
2523 else if(0 == (block->tracks = calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track))))
2524 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2525
2526 for(i = 0; i < block->num_tracks; i++) {
2527 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i)))
2528 return status;
2529 }
2530
2531 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2532 }
2533
read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__byte ** data,FLAC__uint32 * length,FLAC__uint32 length_len)2534 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len)
2535 {
2536 FLAC__byte buffer[sizeof(FLAC__uint32)];
2537
2538 FLAC__ASSERT(0 != data);
2539 FLAC__ASSERT(length_len%8 == 0);
2540
2541 length_len /= 8; /* convert to bytes */
2542
2543 FLAC__ASSERT(sizeof(buffer) >= length_len);
2544
2545 if(read_cb(buffer, 1, length_len, handle) != length_len)
2546 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2547 *length = unpack_uint32_(buffer, length_len);
2548
2549 if(*length > (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) /* data cannot be larger than FLAC metadata block */
2550 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
2551
2552 if(0 != *data)
2553 free(*data);
2554
2555 if(0 == (*data = safe_malloc_add_2op_(*length, /*+*/1)))
2556 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2557
2558 if(*length > 0) {
2559 if(read_cb(*data, 1, *length, handle) != *length)
2560 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2561 }
2562
2563 (*data)[*length] = '\0';
2564
2565 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2566 }
2567
read_metadata_block_data_picture_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_Picture * block)2568 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block)
2569 {
2570 FLAC__Metadata_SimpleIteratorStatus status;
2571 FLAC__byte buffer[4]; /* asserted below that this is big enough */
2572 FLAC__uint32 len;
2573
2574 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
2575 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
2576 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
2577 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
2578 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8);
2579
2580 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0);
2581 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8;
2582 if(read_cb(buffer, 1, len, handle) != len)
2583 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2584 block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len);
2585
2586 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
2587 return status;
2588
2589 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
2590 return status;
2591
2592 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0);
2593 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8;
2594 if(read_cb(buffer, 1, len, handle) != len)
2595 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2596 block->width = unpack_uint32_(buffer, len);
2597
2598 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0);
2599 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8;
2600 if(read_cb(buffer, 1, len, handle) != len)
2601 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2602 block->height = unpack_uint32_(buffer, len);
2603
2604 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0);
2605 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8;
2606 if(read_cb(buffer, 1, len, handle) != len)
2607 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2608 block->depth = unpack_uint32_(buffer, len);
2609
2610 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0);
2611 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8;
2612 if(read_cb(buffer, 1, len, handle) != len)
2613 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2614 block->colors = unpack_uint32_(buffer, len);
2615
2616 /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */
2617 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
2618 return status;
2619
2620 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2621 }
2622
read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__StreamMetadata_Unknown * block,uint32_t block_length)2623 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, uint32_t block_length)
2624 {
2625 if(block_length == 0) {
2626 block->data = 0;
2627 }
2628 else {
2629 if(0 == (block->data = malloc(block_length)))
2630 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2631
2632 if(read_cb(block->data, 1, block_length, handle) != block_length)
2633 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2634 }
2635
2636 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2637 }
2638
write_metadata_block_header_(FILE * file,FLAC__Metadata_SimpleIteratorStatus * status,const FLAC__StreamMetadata * block)2639 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
2640 {
2641 FLAC__ASSERT(0 != file);
2642 FLAC__ASSERT(0 != status);
2643
2644 if(!write_metadata_block_header_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) {
2645 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2646 return false;
2647 }
2648
2649 return true;
2650 }
2651
write_metadata_block_data_(FILE * file,FLAC__Metadata_SimpleIteratorStatus * status,const FLAC__StreamMetadata * block)2652 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
2653 {
2654 FLAC__ASSERT(0 != file);
2655 FLAC__ASSERT(0 != status);
2656
2657 if (write_metadata_block_data_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) {
2658 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2659 return true;
2660 }
2661 else {
2662 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2663 return false;
2664 }
2665 }
2666
write_metadata_block_header_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata * block)2667 FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block)
2668 {
2669 FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
2670
2671 FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
2672 /* double protection */
2673 if(block->length >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
2674 return false;
2675
2676 buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type;
2677 pack_uint32_(block->length, buffer + 1, 3);
2678
2679 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH)
2680 return false;
2681
2682 return true;
2683 }
2684
write_metadata_block_data_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata * block)2685 FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block)
2686 {
2687 FLAC__ASSERT(0 != block);
2688
2689 switch(block->type) {
2690 case FLAC__METADATA_TYPE_STREAMINFO:
2691 return write_metadata_block_data_streaminfo_cb_(handle, write_cb, &block->data.stream_info);
2692 case FLAC__METADATA_TYPE_PADDING:
2693 return write_metadata_block_data_padding_cb_(handle, write_cb, &block->data.padding, block->length);
2694 case FLAC__METADATA_TYPE_APPLICATION:
2695 return write_metadata_block_data_application_cb_(handle, write_cb, &block->data.application, block->length);
2696 case FLAC__METADATA_TYPE_SEEKTABLE:
2697 return write_metadata_block_data_seektable_cb_(handle, write_cb, &block->data.seek_table);
2698 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
2699 return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment);
2700 case FLAC__METADATA_TYPE_CUESHEET:
2701 return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet);
2702 case FLAC__METADATA_TYPE_PICTURE:
2703 return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture);
2704 default:
2705 return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length);
2706 }
2707 }
2708
write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_StreamInfo * block)2709 FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block)
2710 {
2711 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
2712 const uint32_t channels1 = block->channels - 1;
2713 const uint32_t bps1 = block->bits_per_sample - 1;
2714
2715 /* we are using hardcoded numbers for simplicity but we should
2716 * probably eventually write a bit-level packer and use the
2717 * _STREAMINFO_ constants.
2718 */
2719 pack_uint32_(block->min_blocksize, buffer, 2);
2720 pack_uint32_(block->max_blocksize, buffer+2, 2);
2721 pack_uint32_(block->min_framesize, buffer+4, 3);
2722 pack_uint32_(block->max_framesize, buffer+7, 3);
2723 buffer[10] = (block->sample_rate >> 12) & 0xff;
2724 buffer[11] = (block->sample_rate >> 4) & 0xff;
2725 buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4);
2726 buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f));
2727 pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4);
2728 memcpy(buffer+18, block->md5sum, 16);
2729
2730 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
2731 return false;
2732
2733 return true;
2734 }
2735
write_metadata_block_data_padding_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_Padding * block,uint32_t block_length)2736 FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, uint32_t block_length)
2737 {
2738 uint32_t i, n = block_length;
2739 FLAC__byte buffer[1024];
2740
2741 (void)block;
2742
2743 memset(buffer, 0, 1024);
2744
2745 for(i = 0; i < n/1024; i++)
2746 if(write_cb(buffer, 1, 1024, handle) != 1024)
2747 return false;
2748
2749 n %= 1024;
2750
2751 if(write_cb(buffer, 1, n, handle) != n)
2752 return false;
2753
2754 return true;
2755 }
2756
write_metadata_block_data_application_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_Application * block,uint32_t block_length)2757 FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, uint32_t block_length)
2758 {
2759 const uint32_t id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
2760
2761 if(write_cb(block->id, 1, id_bytes, handle) != id_bytes)
2762 return false;
2763
2764 block_length -= id_bytes;
2765
2766 if(write_cb(block->data, 1, block_length, handle) != block_length)
2767 return false;
2768
2769 return true;
2770 }
2771
write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_SeekTable * block)2772 FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block)
2773 {
2774 uint32_t i;
2775 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
2776
2777 for(i = 0; i < block->num_points; i++) {
2778 /* some MAGIC NUMBERs here */
2779 pack_uint64_(block->points[i].sample_number, buffer, 8);
2780 pack_uint64_(block->points[i].stream_offset, buffer+8, 8);
2781 pack_uint32_(block->points[i].frame_samples, buffer+16, 2);
2782 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
2783 return false;
2784 }
2785
2786 return true;
2787 }
2788
write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_VorbisComment * block)2789 FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block)
2790 {
2791 uint32_t i;
2792 const uint32_t entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
2793 const uint32_t num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2794 FLAC__byte buffer[4]; /* magic number is asserted below */
2795
2796 FLAC__ASSERT(flac_max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer));
2797
2798 pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
2799 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
2800 return false;
2801 if(write_cb(block->vendor_string.entry, 1, block->vendor_string.length, handle) != block->vendor_string.length)
2802 return false;
2803
2804 pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len);
2805 if(write_cb(buffer, 1, num_comments_len, handle) != num_comments_len)
2806 return false;
2807
2808 for(i = 0; i < block->num_comments; i++) {
2809 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len);
2810 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
2811 return false;
2812 if(write_cb(block->comments[i].entry, 1, block->comments[i].length, handle) != block->comments[i].length)
2813 return false;
2814 }
2815
2816 return true;
2817 }
2818
write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_CueSheet * block)2819 FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block)
2820 {
2821 uint32_t i, j, len;
2822 FLAC__byte buffer[1024]; /* asserted below that this is big enough */
2823
2824 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64));
2825 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN/8);
2826 FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)/8);
2827 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8);
2828
2829 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
2830 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8;
2831 if(write_cb(block->media_catalog_number, 1, len, handle) != len)
2832 return false;
2833
2834 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0);
2835 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8;
2836 pack_uint64_(block->lead_in, buffer, len);
2837 if(write_cb(buffer, 1, len, handle) != len)
2838 return false;
2839
2840 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0);
2841 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8;
2842 memset(buffer, 0, len);
2843 if(block->is_cd)
2844 buffer[0] |= 0x80;
2845 if(write_cb(buffer, 1, len, handle) != len)
2846 return false;
2847
2848 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0);
2849 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8;
2850 pack_uint32_(block->num_tracks, buffer, len);
2851 if(write_cb(buffer, 1, len, handle) != len)
2852 return false;
2853
2854 for(i = 0; i < block->num_tracks; i++) {
2855 FLAC__StreamMetadata_CueSheet_Track *track = block->tracks + i;
2856
2857 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0);
2858 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8;
2859 pack_uint64_(track->offset, buffer, len);
2860 if(write_cb(buffer, 1, len, handle) != len)
2861 return false;
2862
2863 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0);
2864 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8;
2865 pack_uint32_(track->number, buffer, len);
2866 if(write_cb(buffer, 1, len, handle) != len)
2867 return false;
2868
2869 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
2870 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8;
2871 if(write_cb(track->isrc, 1, len, handle) != len)
2872 return false;
2873
2874 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0);
2875 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8;
2876 memset(buffer, 0, len);
2877 buffer[0] = (track->type << 7) | (track->pre_emphasis << 6);
2878 if(write_cb(buffer, 1, len, handle) != len)
2879 return false;
2880
2881 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0);
2882 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8;
2883 pack_uint32_(track->num_indices, buffer, len);
2884 if(write_cb(buffer, 1, len, handle) != len)
2885 return false;
2886
2887 for(j = 0; j < track->num_indices; j++) {
2888 FLAC__StreamMetadata_CueSheet_Index *indx = track->indices + j;
2889
2890 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0);
2891 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8;
2892 pack_uint64_(indx->offset, buffer, len);
2893 if(write_cb(buffer, 1, len, handle) != len)
2894 return false;
2895
2896 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0);
2897 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8;
2898 pack_uint32_(indx->number, buffer, len);
2899 if(write_cb(buffer, 1, len, handle) != len)
2900 return false;
2901
2902 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0);
2903 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8;
2904 memset(buffer, 0, len);
2905 if(write_cb(buffer, 1, len, handle) != len)
2906 return false;
2907 }
2908 }
2909
2910 return true;
2911 }
2912
write_metadata_block_data_picture_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_Picture * block)2913 FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block)
2914 {
2915 uint32_t len;
2916 size_t slen;
2917 FLAC__byte buffer[4]; /* magic number is asserted below */
2918
2919 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8);
2920 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8);
2921 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8);
2922 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8);
2923 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8);
2924 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8);
2925 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8);
2926 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8);
2927 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
2928 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8);
2929 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8);
2930 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
2931 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
2932 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
2933 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8);
2934 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8);
2935
2936 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8;
2937 pack_uint32_(block->type, buffer, len);
2938 if(write_cb(buffer, 1, len, handle) != len)
2939 return false;
2940
2941 len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8;
2942 slen = strlen(block->mime_type);
2943 pack_uint32_(slen, buffer, len);
2944 if(write_cb(buffer, 1, len, handle) != len)
2945 return false;
2946 if(write_cb(block->mime_type, 1, slen, handle) != slen)
2947 return false;
2948
2949 len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8;
2950 slen = strlen((const char *)block->description);
2951 pack_uint32_(slen, buffer, len);
2952 if(write_cb(buffer, 1, len, handle) != len)
2953 return false;
2954 if(write_cb(block->description, 1, slen, handle) != slen)
2955 return false;
2956
2957 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8;
2958 pack_uint32_(block->width, buffer, len);
2959 if(write_cb(buffer, 1, len, handle) != len)
2960 return false;
2961
2962 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8;
2963 pack_uint32_(block->height, buffer, len);
2964 if(write_cb(buffer, 1, len, handle) != len)
2965 return false;
2966
2967 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8;
2968 pack_uint32_(block->depth, buffer, len);
2969 if(write_cb(buffer, 1, len, handle) != len)
2970 return false;
2971
2972 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8;
2973 pack_uint32_(block->colors, buffer, len);
2974 if(write_cb(buffer, 1, len, handle) != len)
2975 return false;
2976
2977 len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8;
2978 pack_uint32_(block->data_length, buffer, len);
2979 if(write_cb(buffer, 1, len, handle) != len)
2980 return false;
2981 if(write_cb(block->data, 1, block->data_length, handle) != block->data_length)
2982 return false;
2983
2984 return true;
2985 }
2986
write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Write write_cb,const FLAC__StreamMetadata_Unknown * block,uint32_t block_length)2987 FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, uint32_t block_length)
2988 {
2989 if(write_cb(block->data, 1, block_length, handle) != block_length)
2990 return false;
2991
2992 return true;
2993 }
2994
write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator * iterator,const FLAC__StreamMetadata * block)2995 FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block)
2996 {
2997 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2998 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2999 return false;
3000 }
3001
3002 if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
3003 return false;
3004
3005 if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
3006 return false;
3007
3008 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
3009 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3010 return false;
3011 }
3012
3013 return read_metadata_block_header_(iterator);
3014 }
3015
write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator * iterator,FLAC__StreamMetadata * block,uint32_t padding_length,FLAC__bool padding_is_last)3016 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, uint32_t padding_length, FLAC__bool padding_is_last)
3017 {
3018 FLAC__StreamMetadata *padding;
3019
3020 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
3021 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3022 return false;
3023 }
3024
3025 block->is_last = false;
3026
3027 if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
3028 return false;
3029
3030 if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
3031 return false;
3032
3033 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
3034 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
3035
3036 padding->is_last = padding_is_last;
3037 padding->length = padding_length;
3038
3039 if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) {
3040 FLAC__metadata_object_delete(padding);
3041 return false;
3042 }
3043
3044 if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) {
3045 FLAC__metadata_object_delete(padding);
3046 return false;
3047 }
3048
3049 FLAC__metadata_object_delete(padding);
3050
3051 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
3052 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3053 return false;
3054 }
3055
3056 return read_metadata_block_header_(iterator);
3057 }
3058
rewrite_whole_file_(FLAC__Metadata_SimpleIterator * iterator,FLAC__StreamMetadata * block,FLAC__bool append)3059 FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append)
3060 {
3061 FILE *tempfile = NULL;
3062 char *tempfilename = NULL;
3063 int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
3064 FLAC__off_t fixup_is_last_flag_offset = -1;
3065
3066 FLAC__ASSERT(0 != block || append == false);
3067
3068 if(iterator->is_last) {
3069 if(append) {
3070 fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */
3071 fixup_is_last_flag_offset = iterator->offset[iterator->depth];
3072 }
3073 else if(0 == block) {
3074 simple_iterator_push_(iterator);
3075 if(!FLAC__metadata_simple_iterator_prev(iterator)) {
3076 (void)simple_iterator_pop_(iterator);
3077 return false;
3078 }
3079 fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */
3080 fixup_is_last_flag_offset = iterator->offset[iterator->depth];
3081 if(!simple_iterator_pop_(iterator))
3082 return false;
3083 }
3084 }
3085
3086 if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append))
3087 return false;
3088
3089 if(0 != block) {
3090 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) {
3091 cleanup_tempfile_(&tempfile, &tempfilename);
3092 return false;
3093 }
3094
3095 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) {
3096 cleanup_tempfile_(&tempfile, &tempfilename);
3097 return false;
3098 }
3099 }
3100
3101 if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0))
3102 return false;
3103
3104 if(append)
3105 return FLAC__metadata_simple_iterator_next(iterator);
3106
3107 return true;
3108 }
3109
simple_iterator_push_(FLAC__Metadata_SimpleIterator * iterator)3110 void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator)
3111 {
3112 FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH);
3113 iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth];
3114 iterator->depth++;
3115 }
3116
simple_iterator_pop_(FLAC__Metadata_SimpleIterator * iterator)3117 FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator)
3118 {
3119 FLAC__ASSERT(iterator->depth > 0);
3120 iterator->depth--;
3121 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
3122 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3123 return false;
3124 }
3125
3126 return read_metadata_block_header_(iterator);
3127 }
3128
3129 /* return meanings:
3130 * 0: ok
3131 * 1: read error
3132 * 2: seek error
3133 * 3: not a FLAC file
3134 */
seek_to_first_metadata_block_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Seek seek_cb)3135 uint32_t seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb)
3136 {
3137 FLAC__byte buffer[4];
3138 size_t n;
3139 uint32_t i;
3140
3141 FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer));
3142
3143 /* skip any id3v2 tag */
3144 errno = 0;
3145 n = read_cb(buffer, 1, 4, handle);
3146 if(errno)
3147 return 1;
3148 else if(n != 4)
3149 return 3;
3150 else if(0 == memcmp(buffer, "ID3", 3)) {
3151 uint32_t tag_length = 0;
3152
3153 /* skip to the tag length */
3154 if(seek_cb(handle, 2, SEEK_CUR) < 0)
3155 return 2;
3156
3157 /* read the length */
3158 for(i = 0; i < 4; i++) {
3159 if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80)
3160 return 1;
3161 tag_length <<= 7;
3162 tag_length |= (buffer[0] & 0x7f);
3163 }
3164
3165 /* skip the rest of the tag */
3166 if(seek_cb(handle, tag_length, SEEK_CUR) < 0)
3167 return 2;
3168
3169 /* read the stream sync code */
3170 errno = 0;
3171 n = read_cb(buffer, 1, 4, handle);
3172 if(errno)
3173 return 1;
3174 else if(n != 4)
3175 return 3;
3176 }
3177
3178 /* check for the fLaC signature */
3179 if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH))
3180 return 0;
3181 else
3182 return 3;
3183 }
3184
seek_to_first_metadata_block_(FILE * f)3185 uint32_t seek_to_first_metadata_block_(FILE *f)
3186 {
3187 return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_);
3188 }
3189
simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator * iterator,FILE ** tempfile,char ** tempfilename,FLAC__bool append)3190 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
3191 {
3192 const FLAC__off_t offset_end = append? iterator->offset[iterator->depth] + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (FLAC__off_t)iterator->length : iterator->offset[iterator->depth];
3193
3194 if(0 != fseeko(iterator->file, 0, SEEK_SET)) {
3195 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3196 return false;
3197 }
3198 if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) {
3199 cleanup_tempfile_(tempfile, tempfilename);
3200 return false;
3201 }
3202 if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) {
3203 cleanup_tempfile_(tempfile, tempfilename);
3204 return false;
3205 }
3206
3207 return true;
3208 }
3209
simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator * iterator,FILE ** tempfile,char ** tempfilename,int fixup_is_last_code,FLAC__off_t fixup_is_last_flag_offset,FLAC__bool backup)3210 FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, FLAC__off_t fixup_is_last_flag_offset, FLAC__bool backup)
3211 {
3212 FLAC__off_t save_offset = iterator->offset[iterator->depth];
3213 FLAC__ASSERT(0 != *tempfile);
3214
3215 if(0 != fseeko(iterator->file, save_offset + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (FLAC__off_t)iterator->length, SEEK_SET)) {
3216 cleanup_tempfile_(tempfile, tempfilename);
3217 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3218 return false;
3219 }
3220 if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) {
3221 cleanup_tempfile_(tempfile, tempfilename);
3222 return false;
3223 }
3224
3225 if(fixup_is_last_code != 0) {
3226 /*
3227 * if code == 1, it means a block was appended to the end so
3228 * we have to clear the is_last flag of the previous block
3229 * if code == -1, it means the last block was deleted so
3230 * we have to set the is_last flag of the previous block
3231 */
3232 /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
3233 FLAC__byte x;
3234 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
3235 cleanup_tempfile_(tempfile, tempfilename);
3236 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3237 return false;
3238 }
3239 if(fread(&x, 1, 1, *tempfile) != 1) {
3240 cleanup_tempfile_(tempfile, tempfilename);
3241 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
3242 return false;
3243 }
3244 if(fixup_is_last_code > 0) {
3245 FLAC__ASSERT(x & 0x80);
3246 x &= 0x7f;
3247 }
3248 else {
3249 FLAC__ASSERT(!(x & 0x80));
3250 x |= 0x80;
3251 }
3252 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
3253 cleanup_tempfile_(tempfile, tempfilename);
3254 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
3255 return false;
3256 }
3257 if(local__fwrite(&x, 1, 1, *tempfile) != 1) {
3258 cleanup_tempfile_(tempfile, tempfilename);
3259 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
3260 return false;
3261 }
3262 }
3263
3264 (void)fclose(iterator->file);
3265
3266 if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status))
3267 return false;
3268
3269 if(iterator->has_stats)
3270 set_file_stats_(iterator->filename, &iterator->stats);
3271
3272 if(!simple_iterator_prime_input_(iterator, !iterator->is_writable))
3273 return false;
3274 if(backup) {
3275 while(iterator->offset[iterator->depth] + (FLAC__off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (FLAC__off_t)iterator->length < save_offset)
3276 if(!FLAC__metadata_simple_iterator_next(iterator))
3277 return false;
3278 return true;
3279 }
3280 else {
3281 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */
3282 FLAC__ASSERT(iterator->depth == 0);
3283 iterator->offset[0] = save_offset;
3284 iterator->depth++;
3285 return simple_iterator_pop_(iterator);
3286 }
3287 }
3288
copy_n_bytes_from_file_(FILE * file,FILE * tempfile,FLAC__off_t bytes,FLAC__Metadata_SimpleIteratorStatus * status)3289 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status)
3290 {
3291 FLAC__byte buffer[8192];
3292 size_t n;
3293
3294 FLAC__ASSERT(bytes >= 0);
3295 while(bytes > 0) {
3296 n = flac_min(sizeof(buffer), (size_t)bytes);
3297 if(fread(buffer, 1, n, file) != n) {
3298 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
3299 return false;
3300 }
3301 if(local__fwrite(buffer, 1, n, tempfile) != n) {
3302 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
3303 return false;
3304 }
3305 bytes -= n;
3306 }
3307
3308 return true;
3309 }
3310
copy_n_bytes_from_file_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOHandle temp_handle,FLAC__IOCallback_Write temp_write_cb,FLAC__off_t bytes,FLAC__Metadata_SimpleIteratorStatus * status)3311 FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status)
3312 {
3313 FLAC__byte buffer[8192];
3314 size_t n;
3315
3316 FLAC__ASSERT(bytes >= 0);
3317 while(bytes > 0) {
3318 n = flac_min(sizeof(buffer), (size_t)bytes);
3319 if(read_cb(buffer, 1, n, handle) != n) {
3320 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
3321 return false;
3322 }
3323 if(temp_write_cb(buffer, 1, n, temp_handle) != n) {
3324 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
3325 return false;
3326 }
3327 bytes -= n;
3328 }
3329
3330 return true;
3331 }
3332
copy_remaining_bytes_from_file_(FILE * file,FILE * tempfile,FLAC__Metadata_SimpleIteratorStatus * status)3333 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status)
3334 {
3335 FLAC__byte buffer[8192];
3336 size_t n;
3337
3338 while(!feof(file)) {
3339 n = fread(buffer, 1, sizeof(buffer), file);
3340 if(n == 0 && !feof(file)) {
3341 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
3342 return false;
3343 }
3344 if(n > 0 && local__fwrite(buffer, 1, n, tempfile) != n) {
3345 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
3346 return false;
3347 }
3348 }
3349
3350 return true;
3351 }
3352
copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle,FLAC__IOCallback_Read read_cb,FLAC__IOCallback_Eof eof_cb,FLAC__IOHandle temp_handle,FLAC__IOCallback_Write temp_write_cb,FLAC__Metadata_SimpleIteratorStatus * status)3353 FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status)
3354 {
3355 FLAC__byte buffer[8192];
3356 size_t n;
3357
3358 while(!eof_cb(handle)) {
3359 n = read_cb(buffer, 1, sizeof(buffer), handle);
3360 if(n == 0 && !eof_cb(handle)) {
3361 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
3362 return false;
3363 }
3364 if(n > 0 && temp_write_cb(buffer, 1, n, temp_handle) != n) {
3365 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
3366 return false;
3367 }
3368 }
3369
3370 return true;
3371 }
3372
3373 static int
local_snprintf(char * str,size_t size,const char * fmt,...)3374 local_snprintf(char *str, size_t size, const char *fmt, ...)
3375 {
3376 va_list va;
3377 int rc;
3378
3379 #if defined _MSC_VER
3380 if (size == 0)
3381 return 1024;
3382 #endif
3383
3384 va_start (va, fmt);
3385
3386 #if defined _MSC_VER
3387 rc = vsnprintf_s (str, size, _TRUNCATE, fmt, va);
3388 if (rc < 0)
3389 rc = size - 1;
3390 #elif defined __MINGW32__
3391 rc = __mingw_vsnprintf (str, size, fmt, va);
3392 #else
3393 rc = vsnprintf (str, size, fmt, va);
3394 #endif
3395 va_end (va);
3396
3397 return rc;
3398 }
3399
open_tempfile_(const char * filename,const char * tempfile_path_prefix,FILE ** tempfile,char ** tempfilename,FLAC__Metadata_SimpleIteratorStatus * status)3400 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
3401 {
3402 static const char *tempfile_suffix = ".metadata_edit";
3403 if(0 == tempfile_path_prefix) {
3404 size_t dest_len = strlen(filename) + strlen(tempfile_suffix) + 1;
3405 if(0 == (*tempfilename = safe_malloc_(dest_len))) {
3406 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
3407 return false;
3408 }
3409 local_snprintf(*tempfilename, dest_len, "%s%s", filename, tempfile_suffix);
3410 }
3411 else {
3412 const char *p = strrchr(filename, '/');
3413 size_t dest_len;
3414 if(0 == p)
3415 p = filename;
3416 else
3417 p++;
3418
3419 dest_len = strlen(tempfile_path_prefix) + strlen(p) + strlen(tempfile_suffix) + 2;
3420
3421 if(0 == (*tempfilename = safe_malloc_(dest_len))) {
3422 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
3423 return false;
3424 }
3425 local_snprintf(*tempfilename, dest_len, "%s/%s%s", tempfile_path_prefix, p, tempfile_suffix);
3426 }
3427
3428 if(0 == (*tempfile = flac_fopen(*tempfilename, "w+b"))) {
3429 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
3430 return false;
3431 }
3432
3433 return true;
3434 }
3435
transport_tempfile_(const char * filename,FILE ** tempfile,char ** tempfilename,FLAC__Metadata_SimpleIteratorStatus * status)3436 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
3437 {
3438 FLAC__ASSERT(0 != filename);
3439 FLAC__ASSERT(0 != tempfile);
3440 FLAC__ASSERT(0 != *tempfile);
3441 FLAC__ASSERT(0 != tempfilename);
3442 FLAC__ASSERT(0 != *tempfilename);
3443 FLAC__ASSERT(0 != status);
3444
3445 (void)fclose(*tempfile);
3446 *tempfile = 0;
3447
3448 #if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__
3449 /* on some flavors of windows, flac_rename() will fail if the destination already exists */
3450 if(flac_unlink(filename) < 0) {
3451 cleanup_tempfile_(tempfile, tempfilename);
3452 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR;
3453 return false;
3454 }
3455 #endif
3456
3457 /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just flac_rename(): */
3458 if(0 != flac_rename(*tempfilename, filename)) {
3459 cleanup_tempfile_(tempfile, tempfilename);
3460 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
3461 return false;
3462 }
3463
3464 cleanup_tempfile_(tempfile, tempfilename);
3465
3466 return true;
3467 }
3468
cleanup_tempfile_(FILE ** tempfile,char ** tempfilename)3469 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
3470 {
3471 if(0 != *tempfile) {
3472 (void)fclose(*tempfile);
3473 *tempfile = 0;
3474 }
3475
3476 if(0 != *tempfilename) {
3477 (void)flac_unlink(*tempfilename);
3478 free(*tempfilename);
3479 *tempfilename = 0;
3480 }
3481 }
3482
get_file_stats_(const char * filename,struct flac_stat_s * stats)3483 FLAC__bool get_file_stats_(const char *filename, struct flac_stat_s *stats)
3484 {
3485 FLAC__ASSERT(0 != filename);
3486 FLAC__ASSERT(0 != stats);
3487 return (0 == flac_stat(filename, stats));
3488 }
3489
set_file_stats_(const char * filename,struct flac_stat_s * stats)3490 void set_file_stats_(const char *filename, struct flac_stat_s *stats)
3491 {
3492 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) && !defined(_WIN32)
3493 struct timespec srctime[2] = {};
3494 srctime[0].tv_sec = stats->st_atime;
3495 srctime[1].tv_sec = stats->st_mtime;
3496 #else
3497 struct utimbuf srctime;
3498 srctime.actime = stats->st_atime;
3499 srctime.modtime = stats->st_mtime;
3500 #endif
3501
3502 FLAC__ASSERT(0 != filename);
3503 FLAC__ASSERT(0 != stats);
3504
3505 (void)flac_chmod(filename, stats->st_mode);
3506 (void)flac_utime(filename, &srctime);
3507 #if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__
3508 FLAC_CHECK_RETURN(chown(filename, stats->st_uid, -1));
3509 FLAC_CHECK_RETURN(chown(filename, -1, stats->st_gid));
3510 #endif
3511 }
3512
fseek_wrapper_(FLAC__IOHandle handle,FLAC__int64 offset,int whence)3513 int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
3514 {
3515 return fseeko((FILE*)handle, (FLAC__off_t)offset, whence);
3516 }
3517
ftell_wrapper_(FLAC__IOHandle handle)3518 FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle)
3519 {
3520 return ftello((FILE*)handle);
3521 }
3522
get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)3523 FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)
3524 {
3525 switch(status) {
3526 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK:
3527 return FLAC__METADATA_CHAIN_STATUS_OK;
3528 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
3529 return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT;
3530 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
3531 return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
3532 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
3533 return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
3534 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE:
3535 return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE;
3536 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA:
3537 return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
3538 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR:
3539 return FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
3540 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR:
3541 return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
3542 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR:
3543 return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
3544 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR:
3545 return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR;
3546 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR:
3547 return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR;
3548 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR:
3549 return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
3550 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR:
3551 default:
3552 return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
3553 }
3554 }
3555