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