01369cecf0810bbba667a9d3c9d38568ebd72d94
[flac.git] / src / libFLAC / metadata.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2001,2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 #else
29 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
30 #include <utime.h> /* for utime() */
31 #include <unistd.h> /* for chown(), unlink() */
32 #endif
33 #include <sys/stat.h> /* for stat(), maybe chmod() */
34
35 #include "FLAC/assert.h"
36 #include "FLAC/metadata.h"
37 #include "FLAC/file_decoder.h"
38
39 #ifdef max
40 #undef max
41 #endif
42 #define max(a,b) ((a)>(b)?(a):(b))
43 #ifdef min
44 #undef min
45 #endif
46 #define min(a,b) ((a)<(b)?(a):(b))
47
48
49 /****************************************************************************
50  *
51  * Local function declarations
52  *
53  ***************************************************************************/
54
55 /* this one should probably not go in the public interface: */
56 static void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object);
57
58 static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
59 static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
60 static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes);
61 static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes);
62 static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes);
63 static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes);
64
65 static FLAC__bool read_metadata_block_header_(FLAC__MetaData_SimpleIterator *iterator);
66 static FLAC__bool read_metadata_block_data_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block);
67 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetaData_StreamInfo *block);
68 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetaData_Padding *block, unsigned block_length);
69 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetaData_Application *block, unsigned block_length);
70 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetaData_SeekTable *block, unsigned block_length);
71 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetaData_VorbisComment_Entry *entry);
72 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetaData_VorbisComment *block);
73
74 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block);
75 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block);
76 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetaData_StreamInfo *block);
77 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetaData_Padding *block, unsigned block_length);
78 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetaData_Application *block, unsigned block_length);
79 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetaData_SeekTable *block);
80 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetaData_VorbisComment *block);
81 static FLAC__bool write_metadata_block_stationary_(FLAC__MetaData_SimpleIterator *iterator, const FLAC__StreamMetaData *block);
82 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, unsigned padding_length, FLAC__bool padding_is_last);
83 static FLAC__bool rewrite_whole_file_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool append);
84
85 static FLAC__bool chain_rewrite_chain_(FLAC__MetaData_Chain *chain);
86 static FLAC__bool chain_rewrite_file_(FLAC__MetaData_Chain *chain, const char *tempfile_path_prefix);
87
88 static void simple_iterator_push_(FLAC__MetaData_SimpleIterator *iterator);
89 static FLAC__bool simple_iterator_pop_(FLAC__MetaData_SimpleIterator *iterator);
90
91 /* return 0 if OK, 1 if read error, 2 if not a FLAC file */
92 static unsigned seek_to_first_metadata_block_(FILE *f);
93
94 static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append);
95 static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, long fixup_is_last_flag_offset, FLAC__bool backup);
96
97 static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__MetaData_SimpleIteratorStatus *status);
98 static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__MetaData_SimpleIteratorStatus *status);
99
100 static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status);
101 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status);
102 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename);
103
104 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats);
105 static void set_file_stats_(const char *filename, struct stat *stats);
106
107 static FLAC__MetaData_ChainStatus get_equivalent_status_(FLAC__MetaData_SimpleIteratorStatus status);
108
109
110 /****************************************************************************
111  *
112  * Level 0 implementation
113  *
114  ***************************************************************************/
115
116 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
117 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
118 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
119
120 FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetaData_StreamInfo *streaminfo)
121 {
122         FLAC__FileDecoder *decoder = FLAC__file_decoder_new();
123
124         if(0 == decoder)
125                 return false;
126
127         FLAC__file_decoder_set_md5_checking(decoder, false);
128         FLAC__file_decoder_set_filename(decoder, filename);
129         FLAC__file_decoder_set_write_callback(decoder, write_callback_);
130         FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
131         FLAC__file_decoder_set_error_callback(decoder, error_callback_);
132         FLAC__file_decoder_set_client_data(decoder, &streaminfo);
133
134         if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
135                 return false;
136
137         if(!FLAC__file_decoder_process_metadata(decoder))
138                 return false;
139
140         FLAC__file_decoder_finish(decoder);
141         FLAC__file_decoder_delete(decoder);
142
143         return 0 != streaminfo; /* the metadata_callback_() will set streaminfo to 0 on an error */
144 }
145
146 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
147 {
148         (void)decoder, (void)frame, (void)buffer, (void)client_data;
149
150         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
151 }
152
153 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
154 {
155         FLAC__StreamMetaData_StreamInfo **streaminfo = (FLAC__StreamMetaData_StreamInfo **)client_data;
156         (void)decoder;
157
158         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && 0 != *streaminfo)
159                 **streaminfo = metadata->data.stream_info;
160 }
161
162 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
163 {
164         FLAC__StreamMetaData_StreamInfo **streaminfo = (FLAC__StreamMetaData_StreamInfo **)client_data;
165         (void)decoder;
166
167         if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
168                 *streaminfo = 0;
169 }
170
171
172 /****************************************************************************
173  *
174  * Level 1 implementation
175  *
176  ***************************************************************************/
177
178 #define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4)
179 /* 1 for initial offset, +4 for our own personal use */
180
181 struct FLAC__MetaData_SimpleIterator {
182         FILE *file;
183         char *filename, *tempfile_path_prefix;
184         struct stat stats;
185         FLAC__bool has_stats;
186         FLAC__bool is_writable;
187         FLAC__MetaData_SimpleIteratorStatus status;
188         /*@@@ 2G limits here because of the offset type: */
189         long offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
190         long first_offset; /* this is the offset to the STREAMINFO block */
191         unsigned depth;
192         /* this is the metadata block header of the current block we are pointing to: */
193         FLAC__bool is_last;
194         FLAC__MetaDataType type;
195         unsigned length;
196 };
197
198 const char *FLAC__MetaData_SimpleIteratorStatusString[] = {
199         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK",
200         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT",
201         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE",
202         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE",
203         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE",
204         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA",
205         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR",
206         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR",
207         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR",
208         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR",
209         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR",
210         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR",
211         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR"
212 };
213
214
215 FLAC__MetaData_SimpleIterator *FLAC__metadata_simple_iterator_new()
216 {
217         FLAC__MetaData_SimpleIterator *iterator = malloc(sizeof(FLAC__MetaData_SimpleIterator));
218
219         if(0 != iterator) {
220                 iterator->file = 0;
221                 iterator->filename = 0;
222                 iterator->tempfile_path_prefix = 0;
223                 iterator->has_stats = false;
224                 iterator->is_writable = false;
225                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
226                 iterator->first_offset = iterator->offset[0] = -1;
227                 iterator->depth = 0;
228         }
229
230         return iterator;
231 }
232
233 static void simple_iterator_free_guts_(FLAC__MetaData_SimpleIterator *iterator)
234 {
235         FLAC__ASSERT(0 != iterator);
236
237         if(0 != iterator->file) {
238                 fclose(iterator->file);
239                 iterator->file = 0;
240                 if(iterator->has_stats)
241                         set_file_stats_(iterator->filename, &iterator->stats);
242         }
243         if(0 != iterator->filename) {
244                 free(iterator->filename);
245                 iterator->filename = 0;
246         }
247         if(0 != iterator->tempfile_path_prefix) {
248                 free(iterator->tempfile_path_prefix);
249                 iterator->tempfile_path_prefix = 0;
250         }
251 }
252
253 void FLAC__metadata_simple_iterator_delete(FLAC__MetaData_SimpleIterator *iterator)
254 {
255         FLAC__ASSERT(0 != iterator);
256
257         simple_iterator_free_guts_(iterator);
258         free(iterator);
259 }
260
261 FLAC__MetaData_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__MetaData_SimpleIterator *iterator)
262 {
263         FLAC__MetaData_SimpleIteratorStatus status;
264
265         FLAC__ASSERT(0 != iterator);
266
267         status = iterator->status;
268         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
269         return status;
270 }
271
272 static FLAC__bool simple_iterator_prime_input_(FLAC__MetaData_SimpleIterator *iterator)
273 {
274         unsigned ret;
275
276         FLAC__ASSERT(0 != iterator);
277
278         iterator->is_writable = false;
279
280         if(0 == (iterator->file = fopen(iterator->filename, "r+b"))) {
281                 if(errno == EACCES) {
282                         if(0 == (iterator->file = fopen(iterator->filename, "rb"))) {
283                                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
284                                 return false;
285                         }
286                 }
287                 else {
288                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
289                         return false;
290                 }
291         }
292         else {
293                 iterator->is_writable = true;
294         }
295
296         ret = seek_to_first_metadata_block_(iterator->file);
297         switch(ret) {
298                 case 0:
299                         iterator->depth = 0;
300                         iterator->first_offset = iterator->offset[iterator->depth] = ftell(iterator->file);
301                         return read_metadata_block_header_(iterator);
302                 case 1:
303                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
304                         return false;
305                 case 2:
306                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE;
307                         return false;
308                 default:
309                         FLAC__ASSERT(0);
310                         return false;
311         }
312 }
313
314 #if 0
315 @@@ If we decide to finish implementing this, put this comment back in metadata.h
316 /*
317  * The 'tempfile_path_prefix' allows you to specify a directory where
318  * tempfiles should go.  Remember that if your metadata edits cause the
319  * FLAC file to grow, the entire file will have to be rewritten.  If
320  * 'tempfile_path_prefix' is NULL, the temp file will be written in the
321  * same directory as the original FLAC file.  This makes replacing the
322  * original with the tempfile fast but requires extra space in the same
323  * partition for the tempfile.  If space is a problem, you can pass a
324  * directory name belonging to a different partition in
325  * 'tempfile_path_prefix'.  Note that you should use the forward slash
326  * '/' as the directory separator.  A trailing slash is not needed; it
327  * will be added automatically.
328  */
329 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__MetaData_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix);
330 #endif
331
332 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__MetaData_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats)
333 {
334         const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */
335
336         FLAC__ASSERT(0 != iterator);
337         FLAC__ASSERT(0 != filename);
338
339         simple_iterator_free_guts_(iterator);
340
341         if(preserve_file_stats)
342                 iterator->has_stats = get_file_stats_(filename, &iterator->stats);
343
344         if(0 == (iterator->filename = strdup(filename))) {
345                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
346                 return false;
347         }
348         if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) {
349                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
350                 return false;
351         }
352
353         return simple_iterator_prime_input_(iterator);
354 }
355
356 FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__MetaData_SimpleIterator *iterator)
357 {
358         FLAC__ASSERT(0 != iterator);
359         FLAC__ASSERT(0 != iterator->file);
360
361         return iterator->is_writable;
362 }
363
364 FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__MetaData_SimpleIterator *iterator)
365 {
366         FLAC__ASSERT(0 != iterator);
367         FLAC__ASSERT(0 != iterator->file);
368
369         if(iterator->is_last)
370                 return false;
371
372         if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
373                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
374                 return false;
375         }
376
377         iterator->offset[iterator->depth] = ftell(iterator->file);
378
379         return read_metadata_block_header_(iterator);
380 }
381
382 FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__MetaData_SimpleIterator *iterator)
383 {
384         long this_offset;
385
386         FLAC__ASSERT(0 != iterator);
387         FLAC__ASSERT(0 != iterator->file);
388
389         if(iterator->offset[iterator->depth] == iterator->first_offset)
390                 return false;
391
392         if(0 != fseek(iterator->file, iterator->first_offset, SEEK_SET)) {
393                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
394                 return false;
395         }
396         this_offset = iterator->first_offset;
397         if(!read_metadata_block_header_(iterator))
398                 return false;
399
400         /* we ignore any error from ftell() and catch it in fseek() */
401         while(ftell(iterator->file) + (long)iterator->length < iterator->offset[iterator->depth]) {
402                 if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
403                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
404                         return false;
405                 }
406                 this_offset = ftell(iterator->file);
407                 if(!read_metadata_block_header_(iterator))
408                         return false;
409         }
410
411         iterator->offset[iterator->depth] = this_offset;
412
413         return true;
414 }
415
416 FLAC__MetaDataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__MetaData_SimpleIterator *iterator)
417 {
418         FLAC__ASSERT(0 != iterator);
419         FLAC__ASSERT(0 != iterator->file);
420
421         return iterator->type;
422 }
423
424 FLAC__StreamMetaData *FLAC__metadata_simple_iterator_get_block(FLAC__MetaData_SimpleIterator *iterator)
425 {
426         FLAC__StreamMetaData *block = FLAC__metadata_object_new(iterator->type);
427
428         FLAC__ASSERT(0 != iterator);
429         FLAC__ASSERT(0 != iterator->file);
430
431         if(0 != block) {
432                 block->is_last = iterator->is_last;
433                 block->length = iterator->length;
434
435                 if(!read_metadata_block_data_(iterator, block)) {
436                         FLAC__metadata_object_delete(block);
437                         return 0;
438                 }
439
440                 /* back up to the beginning of the block data to stay consistent */
441                 if(0 != fseek(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
442                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
443                         FLAC__metadata_object_delete(block);
444                         return 0;
445                 }
446         }
447         else
448                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
449
450         return block;
451 }
452
453 FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool use_padding)
454 {
455         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
456         FLAC__bool ret;
457
458         FLAC__ASSERT(0 != iterator);
459         FLAC__ASSERT(0 != iterator->file);
460
461         if(!iterator->is_writable) {
462                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
463                 return false;
464         }
465
466         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) {
467                 if(iterator->type != block->type) {
468                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
469                         return false;
470                 }
471         }
472
473         block->is_last = iterator->is_last;
474
475         if(iterator->length == block->length)
476                 return write_metadata_block_stationary_(iterator, block);
477         else if(iterator->length > block->length) {
478                 if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) {
479                         ret =  write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last);
480                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
481                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
482                         return ret;
483                 }
484                 else {
485                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
486                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
487                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
488                         return ret;
489                 }
490         }
491         else /* iterator->length < block->length */ {
492                 unsigned padding_leftover = 0;
493                 FLAC__bool padding_is_last = false;
494                 if(use_padding) {
495                         /* first see if we can even use padding */
496                         if(iterator->is_last) {
497                                 use_padding = false;
498                         }
499                         else {
500                                 const unsigned extra_padding_bytes_required = block->length - iterator->length;
501                                 simple_iterator_push_(iterator);
502                                 if(!FLAC__metadata_simple_iterator_next(iterator)) {
503                                         (void)simple_iterator_pop_(iterator);
504                                         return false;
505                                 }
506                                 if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
507                                         use_padding = false;
508                                 }
509                                 else {
510                                         if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) {
511                                                 padding_leftover = 0;
512                                                 block->is_last = iterator->is_last;
513                                         }
514                                         else if(iterator->length < extra_padding_bytes_required)
515                                                 use_padding = false;
516                                         else {
517                                                 padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required;
518                                                 padding_is_last = iterator->is_last;
519                                                 block->is_last = false;
520                                         }
521                                 }
522                                 if(!simple_iterator_pop_(iterator))
523                                         return false;
524                         }
525                 }
526                 if(use_padding) {
527                         if(padding_leftover == 0) {
528                                 ret = write_metadata_block_stationary_(iterator, block);
529                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
530                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
531                                 return ret;
532                         }
533                         else {
534                                 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
535                                 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
536                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
537                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
538                                 return ret;
539                         }
540                 }
541                 else {
542                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
543                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
544                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
545                         return ret;
546                 }
547         }
548 }
549
550 FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool use_padding)
551 {
552         unsigned padding_leftover = 0;
553         FLAC__bool padding_is_last = false;
554
555         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
556         FLAC__bool ret;
557
558         FLAC__ASSERT(0 != iterator);
559         FLAC__ASSERT(0 != iterator->file);
560
561         if(!iterator->is_writable)
562                 return false;
563
564         if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
565                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
566                 return false;
567         }
568
569         block->is_last = iterator->is_last;
570
571         if(use_padding) {
572                 /* first see if we can even use padding */
573                 if(iterator->is_last) {
574                         use_padding = false;
575                 }
576                 else {
577                         simple_iterator_push_(iterator);
578                         if(!FLAC__metadata_simple_iterator_next(iterator)) {
579                                 (void)simple_iterator_pop_(iterator);
580                                 return false;
581                         }
582                         if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
583                                 use_padding = false;
584                         }
585                         else {
586                                 if(iterator->length == block->length) {
587                                         padding_leftover = 0;
588                                         block->is_last = iterator->is_last;
589                                 }
590                                 else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length)
591                                         use_padding = false;
592                                 else {
593                                         padding_leftover = iterator->length - block->length;
594                                         padding_is_last = iterator->is_last;
595                                         block->is_last = false;
596                                 }
597                         }
598                         if(!simple_iterator_pop_(iterator))
599                                 return false;
600                 }
601         }
602         if(use_padding) {
603                 /* move to the next block, which is suitable padding */
604                 if(!FLAC__metadata_simple_iterator_next(iterator))
605                         return false;
606                 if(padding_leftover == 0) {
607                         ret = write_metadata_block_stationary_(iterator, block);
608                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
609                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
610                         return ret;
611                 }
612                 else {
613                         FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
614                         ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
615                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
616                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
617                         return ret;
618                 }
619         }
620         else {
621                 ret = rewrite_whole_file_(iterator, block, /*append=*/true);
622                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
623                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
624                 return ret;
625         }
626 }
627
628 FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__MetaData_SimpleIterator *iterator, FLAC__bool use_padding)
629 {
630         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
631         FLAC__bool ret;
632
633         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
634                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
635                 return false;
636         }
637
638         if(use_padding) {
639                 FLAC__StreamMetaData *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
640                 if(0 == padding) {
641                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
642                         return false;
643                 }
644                 padding->length = iterator->length;
645                 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) {
646                         FLAC__metadata_object_delete(padding);
647                         return false;
648                 }
649                 FLAC__metadata_object_delete(padding);
650                 if(!FLAC__metadata_simple_iterator_prev(iterator))
651                         return false;
652                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
653                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
654                 return true;
655         }
656         else {
657                 ret = rewrite_whole_file_(iterator, 0, /*append=*/false);
658                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
659                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
660                 return ret;
661         }
662 }
663
664
665
666 /****************************************************************************
667  *
668  * Level 2 implementation
669  *
670  ***************************************************************************/
671
672
673 typedef struct FLAC__MetaData_Node {
674         FLAC__StreamMetaData *data;
675         struct FLAC__MetaData_Node *prev, *next;
676 } FLAC__MetaData_Node;
677
678 struct FLAC__MetaData_Chain {
679         char *filename;
680         FLAC__MetaData_Node *head;
681         FLAC__MetaData_Node *tail;
682         unsigned nodes;
683         FLAC__MetaData_ChainStatus status;
684         long first_offset, last_offset; /*@@@ 2G limit */
685         /*
686          * This is the length of the chain initially read from the FLAC file.
687          * it is used to compare against the current_length to decide whether
688          * or not the whole file has to be rewritten.
689          */
690         unsigned initial_length; /*@@@ 4G limit */
691         unsigned current_length; /*@@@ 4G limit */
692 };
693
694 struct FLAC__MetaData_Iterator {
695         FLAC__MetaData_Chain *chain;
696         FLAC__MetaData_Node *current;
697 };
698
699 const char *FLAC__MetaData_ChainStatusString[] = {
700         "FLAC__METADATA_CHAIN_STATUS_OK",
701         "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT",
702         "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE",
703         "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE",
704         "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE",
705         "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA",
706         "FLAC__METADATA_CHAIN_STATUS_READ_ERROR",
707         "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR",
708         "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR",
709         "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
710         "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
711         "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
712         "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR"
713 };
714
715
716 static FLAC__MetaData_Node *node_new_()
717 {
718         FLAC__MetaData_Node *node = (FLAC__MetaData_Node*)malloc(sizeof(FLAC__MetaData_Node));
719         if(0 != node)
720                 memset(node, 0, sizeof(FLAC__MetaData_Node));
721         return node;
722 }
723
724 static void node_delete_(FLAC__MetaData_Node *node)
725 {
726         FLAC__ASSERT(0 != node);
727         if(0 != node->data)
728                 FLAC__metadata_object_delete(node->data);
729         free(node);
730 }
731
732 static void chain_append_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
733 {
734         FLAC__ASSERT(0 != chain);
735         FLAC__ASSERT(0 != node);
736         FLAC__ASSERT(0 != node->data);
737
738         node->next = node->prev = 0;
739         node->data->is_last = true;
740         if(0 != chain->tail)
741                 chain->tail->data->is_last = false;
742
743         if(0 == chain->head)
744                 chain->head = node;
745         else {
746                 FLAC__ASSERT(0 != chain->tail);
747                 chain->tail->next = node;
748                 node->prev = chain->tail;
749         }
750         chain->tail = node;
751         chain->nodes++;
752         chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
753 }
754
755 static void chain_remove_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
756 {
757         FLAC__ASSERT(0 != chain);
758         FLAC__ASSERT(0 != node);
759
760         if(node == chain->head)
761                 chain->head = node->next;
762         else
763                 node->prev->next = node->next;
764
765         if(node == chain->tail)
766                 chain->tail = node->prev;
767         else
768                 node->next->prev = node->prev;
769
770         if(0 != chain->tail)
771                 chain->tail->data->is_last = true;
772
773         chain->nodes--;
774         chain->current_length -= (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
775 }
776
777 static void chain_delete_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
778 {
779         chain_remove_node_(chain, node);
780         node_delete_(node);
781 }
782
783 static void iterator_insert_node_(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Node *node)
784 {
785         FLAC__ASSERT(0 != node);
786         FLAC__ASSERT(0 != node->data);
787         FLAC__ASSERT(0 != iterator);
788         FLAC__ASSERT(0 != iterator->current);
789         FLAC__ASSERT(0 != iterator->chain);
790         FLAC__ASSERT(0 != iterator->chain->head);
791         FLAC__ASSERT(0 != iterator->chain->tail);
792
793         node->data->is_last = false;
794
795         node->prev = iterator->current->prev;
796         node->next = iterator->current;
797
798         if(0 == node->prev)
799                 iterator->chain->head = node;
800         else
801                 node->prev->next = node;
802
803         iterator->current->prev = node;
804
805         iterator->chain->nodes++;
806         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
807 }
808
809 static void iterator_insert_node_after_(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Node *node)
810 {
811         FLAC__ASSERT(0 != node);
812         FLAC__ASSERT(0 != node->data);
813         FLAC__ASSERT(0 != iterator);
814         FLAC__ASSERT(0 != iterator->current);
815         FLAC__ASSERT(0 != iterator->chain);
816         FLAC__ASSERT(0 != iterator->chain->head);
817         FLAC__ASSERT(0 != iterator->chain->tail);
818
819         iterator->current->data->is_last = false;
820
821         node->prev = iterator->current;
822         node->next = iterator->current->next;
823
824         if(0 == node->next)
825                 iterator->chain->tail = node;
826         else
827                 node->next->prev = node;
828
829         node->prev->next = node;
830
831         iterator->chain->tail->data->is_last = true;
832
833         iterator->chain->nodes++;
834         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
835 }
836
837 /* return true iff node and node->next are both padding */
838 static FLAC__bool chain_merge_adjacent_padding_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
839 {
840         if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) {
841                 const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length;
842                 node->data->length += growth;
843                 chain->current_length += growth;
844
845                 chain_delete_node_(chain, node->next);
846                 return true;
847         }
848         else
849                 return false;
850 }
851
852 FLAC__MetaData_Chain *FLAC__metadata_chain_new()
853 {
854         FLAC__MetaData_Chain *chain = malloc(sizeof(FLAC__MetaData_Chain));
855
856         if(0 != chain) {
857                 chain->filename = 0;
858                 chain->head = chain->tail = 0;
859                 chain->nodes = 0;
860                 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
861                 chain->initial_length = chain->current_length = 0;
862         }
863
864         return chain;
865 }
866
867 void FLAC__metadata_chain_delete(FLAC__MetaData_Chain *chain)
868 {
869         FLAC__MetaData_Node *node, *next;
870
871         FLAC__ASSERT(0 != chain);
872
873         for(node = chain->head; node; ) {
874                 next = node->next;
875                 node_delete_(node);
876                 node = next;
877         }
878
879         if(0 != chain->filename)
880                 free(chain->filename);
881
882         free(chain);
883 }
884
885 FLAC__MetaData_ChainStatus FLAC__metadata_chain_status(FLAC__MetaData_Chain *chain)
886 {
887         FLAC__MetaData_ChainStatus status;
888
889         FLAC__ASSERT(0 != chain);
890
891         status = chain->status;
892         chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
893         return status;
894 }
895
896 FLAC__bool FLAC__metadata_chain_read(FLAC__MetaData_Chain *chain, const char *filename)
897 {
898         FLAC__MetaData_SimpleIterator *iterator;
899         FLAC__MetaData_Node *node;
900
901         FLAC__ASSERT(0 != chain);
902         FLAC__ASSERT(0 != filename);
903
904         if(0 == (chain->filename = strdup(filename))) {
905                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
906                 return false;
907         }
908
909         if(0 == (iterator = FLAC__metadata_simple_iterator_new())) {
910                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
911                 return false;
912         }
913
914         if(!FLAC__metadata_simple_iterator_init(iterator, filename, /*preserve_file_stats=*/false)) {
915                 chain->status = get_equivalent_status_(iterator->status);
916                 return false;
917         }
918
919         chain->first_offset = iterator->offset[iterator->depth];
920
921         do {
922                 node = node_new_();
923                 if(0 == node) {
924                         chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
925                         return false;
926                 }
927                 node->data = FLAC__metadata_simple_iterator_get_block(iterator);
928                 if(0 == node->data) {
929                         node_delete_(node);
930                         chain->status = get_equivalent_status_(iterator->status);
931                         return false;
932                 }
933                 chain_append_node_(chain, node);
934         } while(FLAC__metadata_simple_iterator_next(iterator));
935
936         if(!iterator->is_last || iterator->status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) {
937                 chain->status = get_equivalent_status_(iterator->status);
938                 return false;
939         }
940
941         chain->last_offset = ftell(iterator->file) + iterator->length;
942         FLAC__metadata_simple_iterator_delete(iterator);
943
944         chain->initial_length = chain->current_length;
945         return true;
946 }
947
948 FLAC__bool FLAC__metadata_chain_write(FLAC__MetaData_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
949 {
950         struct stat stats;
951         const char *tempfile_path_prefix = 0;
952
953         if(use_padding) {
954                 if(chain->current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
955                         const unsigned delta = chain->initial_length - chain->current_length;
956                         chain->tail->data->length += delta;
957                         chain->current_length += delta;
958                         FLAC__ASSERT(chain->current_length == chain->initial_length);
959                 }
960                 else if(chain->current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
961                         FLAC__StreamMetaData *padding;
962                         FLAC__MetaData_Node *node;
963                         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
964                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
965                                 return false;
966                         }
967                         padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + chain->current_length);
968                         if(0 == (node = node_new_())) {
969                                 FLAC__metadata_object_delete(padding);
970                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
971                                 return false;
972                         }
973                         node->data = padding;
974                         chain_append_node_(chain, node);
975                         FLAC__ASSERT(chain->current_length == chain->initial_length);
976                 }
977                 else if(chain->current_length > chain->initial_length) {
978                         const unsigned delta = chain->current_length - chain->initial_length;
979                         if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
980                                 if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
981                                         chain_delete_node_(chain, chain->tail);
982                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
983                                 }
984                                 else if(chain->tail->data->length >= delta) {
985                                         chain->tail->data->length -= delta;
986                                         chain->current_length -= delta;
987                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
988                                 }
989                         }
990                 }
991         }
992
993         if(preserve_file_stats)
994                 get_file_stats_(chain->filename, &stats);
995
996         if(chain->current_length == chain->initial_length) {
997                 if(!chain_rewrite_chain_(chain))
998                         return false;
999         }
1000         else {
1001                 if(!chain_rewrite_file_(chain, tempfile_path_prefix))
1002                         return false;
1003         }
1004
1005         if(preserve_file_stats)
1006                 set_file_stats_(chain->filename, &stats);
1007
1008         /* recompute lengths and offsets if necessary */
1009         if(chain->initial_length != chain->current_length) {
1010                 const FLAC__MetaData_Node *node;
1011                 chain->initial_length = chain->current_length;
1012                 chain->last_offset = chain->first_offset;
1013                 for(node = chain->head; node; node = node->next)
1014                         chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1015         }
1016
1017         return true;
1018 }
1019
1020 void FLAC__metadata_chain_merge_padding(FLAC__MetaData_Chain *chain)
1021 {
1022         FLAC__MetaData_Node *node;
1023
1024         FLAC__ASSERT(0 != chain);
1025
1026         for(node = chain->head; node; ) {
1027                 if(!chain_merge_adjacent_padding_(chain, node))
1028                         node = node->next;
1029         }
1030 }
1031
1032 void FLAC__metadata_chain_sort_padding(FLAC__MetaData_Chain *chain)
1033 {
1034         FLAC__MetaData_Node *node, *save;
1035         unsigned i;
1036
1037         FLAC__ASSERT(0 != chain);
1038
1039         /*
1040          * Don't try and be too smart... this simple algo is good enough for
1041          * the small number of nodes that we deal with.
1042          */
1043         for(i = 0, node = chain->head; i < chain->nodes; i++) {
1044                 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1045                         save = node->next;
1046                         chain_remove_node_(chain, node);
1047                         chain_append_node_(chain, node);
1048                         node = save;
1049                 }
1050                 else {
1051                         node = node->next;
1052                 }
1053         }
1054
1055         FLAC__metadata_chain_merge_padding(chain);
1056 }
1057
1058
1059 FLAC__MetaData_Iterator *FLAC__metadata_iterator_new()
1060 {
1061         FLAC__MetaData_Iterator *iterator = malloc(sizeof(FLAC__MetaData_Iterator));
1062
1063         if(0 != iterator) {
1064                 iterator->current = 0;
1065                 iterator->chain = 0;
1066         }
1067
1068         return iterator;
1069 }
1070
1071 void FLAC__metadata_iterator_delete(FLAC__MetaData_Iterator *iterator)
1072 {
1073         FLAC__ASSERT(0 != iterator);
1074
1075         free(iterator);
1076 }
1077
1078 /*
1079  * Initialize the iterator to point to the first metadata block in the
1080  * given chain.
1081  */
1082 void FLAC__metadata_iterator_init(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Chain *chain)
1083 {
1084         FLAC__ASSERT(0 != iterator);
1085         FLAC__ASSERT(0 != chain);
1086         FLAC__ASSERT(0 != chain->head);
1087
1088         iterator->chain = chain;
1089         iterator->current = chain->head;
1090 }
1091
1092 FLAC__bool FLAC__metadata_iterator_next(FLAC__MetaData_Iterator *iterator)
1093 {
1094         FLAC__ASSERT(0 != iterator);
1095
1096         if(0 == iterator->current || 0 == iterator->current->next)
1097                 return false;
1098
1099         iterator->current = iterator->current->next;
1100         return true;
1101 }
1102
1103 FLAC__bool FLAC__metadata_iterator_prev(FLAC__MetaData_Iterator *iterator)
1104 {
1105         FLAC__ASSERT(0 != iterator);
1106
1107         if(0 == iterator->current || 0 == iterator->current->prev)
1108                 return false;
1109
1110         iterator->current = iterator->current->prev;
1111         return true;
1112 }
1113
1114 FLAC__MetaDataType FLAC__metadata_iterator_get_block_type(const FLAC__MetaData_Iterator *iterator)
1115 {
1116         FLAC__ASSERT(0 != iterator);
1117         FLAC__ASSERT(0 != iterator->current);
1118         FLAC__ASSERT(0 != iterator->current->data);
1119
1120         return iterator->current->data->type;
1121 }
1122
1123 FLAC__StreamMetaData *FLAC__metadata_iterator_get_block(FLAC__MetaData_Iterator *iterator)
1124 {
1125         FLAC__ASSERT(0 != iterator);
1126         FLAC__ASSERT(0 != iterator->current);
1127
1128         return iterator->current->data;
1129 }
1130
1131 FLAC__bool FLAC__metadata_iterator_set_block(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1132 {
1133         return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
1134 }
1135
1136 FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__MetaData_Iterator *iterator, FLAC__bool replace_with_padding)
1137 {
1138         FLAC__MetaData_Node *save;
1139
1140         FLAC__ASSERT(0 != iterator);
1141         FLAC__ASSERT(0 != iterator->current);
1142
1143         if(0 == iterator->current->prev) {
1144                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1145                 return false;
1146         }
1147
1148         save = iterator->current->prev;
1149
1150         if(replace_with_padding) {
1151                 FLAC__metadata_object_delete_data_(iterator->current->data);
1152                 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
1153         }
1154         else {
1155                 chain_delete_node_(iterator->chain, iterator->current);
1156         }
1157
1158         iterator->current = save;
1159         return true;
1160 }
1161
1162 FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1163 {
1164         FLAC__MetaData_Node *node;
1165
1166         FLAC__ASSERT(0 != iterator);
1167         FLAC__ASSERT(0 != iterator->current);
1168
1169         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1170                 return false;
1171
1172         if(0 == iterator->current->prev) {
1173                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1174                 return false;
1175         }
1176
1177         if(0 == (node = node_new_()))
1178                 return false;
1179
1180         node->data = block;
1181         iterator_insert_node_(iterator, node);
1182         iterator->current = node;
1183         return true;
1184 }
1185
1186 FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1187 {
1188         FLAC__MetaData_Node *node;
1189
1190         FLAC__ASSERT(0 != iterator);
1191         FLAC__ASSERT(0 != iterator->current);
1192
1193         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1194                 return false;
1195
1196         if(0 == (node = node_new_()))
1197                 return false;
1198
1199         node->data = block;
1200         iterator_insert_node_after_(iterator, node);
1201         iterator->current = node;
1202         return true;
1203 }
1204
1205
1206 /****************************************************************************
1207  *
1208  * Metadata object routines
1209  *
1210  ***************************************************************************/
1211
1212 /*@@@@move
1213 will return pointer to new empty object of type 'type', or 0 if malloc failed
1214 type is valid type
1215 */
1216 FLAC__StreamMetaData *FLAC__metadata_object_new(FLAC__MetaDataType type)
1217 {
1218         FLAC__StreamMetaData *object = malloc(sizeof(FLAC__StreamMetaData));
1219         if(0 != object) {
1220                 memset(object, 0, sizeof(FLAC__StreamMetaData));
1221                 object->is_last = false;
1222                 object->type = type;
1223                 switch(type) {
1224                         case FLAC__METADATA_TYPE_STREAMINFO:
1225                                 object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
1226                                 break;
1227                         case FLAC__METADATA_TYPE_PADDING:
1228                                 break;
1229                         case FLAC__METADATA_TYPE_APPLICATION:
1230                                 object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1231                                 break;
1232                         case FLAC__METADATA_TYPE_SEEKTABLE:
1233                                 break;
1234                         case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1235                                 object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN + FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
1236                                 break;
1237                         default:
1238                                 /* double protection: */
1239                                 FLAC__ASSERT(0);
1240                                 free(object);
1241                                 return 0;
1242                 }
1243         }
1244
1245         return object;
1246 }
1247
1248 static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
1249 {
1250         if(bytes > 0 && 0 != from) {
1251                 if(0 == (*to = malloc(bytes)))
1252                         return false;
1253                 memcpy(*to, from, bytes);
1254         }
1255         else {
1256                 FLAC__ASSERT(0 == from);
1257                 FLAC__ASSERT(bytes == 0);
1258                 *to = 0;
1259         }
1260         return true;
1261 }
1262
1263 static FLAC__bool copy_vcentry_(FLAC__StreamMetaData_VorbisComment_Entry *to, const FLAC__StreamMetaData_VorbisComment_Entry *from)
1264 {
1265         to->length = from->length;
1266         if(0 == from->entry) {
1267                 FLAC__ASSERT(from->length == 0);
1268                 to->entry = 0;
1269         }
1270         else {
1271                 FLAC__ASSERT(from->length > 0);
1272                 if(0 == (to->entry = malloc(from->length)))
1273                         return false;
1274                 memcpy(to->entry, from->entry, from->length);
1275         }
1276         return true;
1277 }
1278
1279 /*@@@@move
1280 return a pointer to a copy of 'object', or 0 if any malloc failed.  does a deep copy.  user gets ownership of object.
1281     FLAC__ASSERT(0 != object);
1282 */
1283 FLAC__StreamMetaData *FLAC__metadata_object_copy(const FLAC__StreamMetaData *object)
1284 {
1285         FLAC__StreamMetaData *to;
1286         unsigned i;
1287
1288         FLAC__ASSERT(0 != object);
1289
1290         if(0 != (to = FLAC__metadata_object_new(object->type))) {
1291                 to->is_last = object->is_last;
1292                 to->type = object->type;
1293                 to->length = object->length;
1294                 switch(to->type) {
1295                         case FLAC__METADATA_TYPE_STREAMINFO:
1296                                 memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetaData_StreamInfo));
1297                                 break;
1298                         case FLAC__METADATA_TYPE_PADDING:
1299                                 break;
1300                         case FLAC__METADATA_TYPE_APPLICATION:
1301                                 memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8);
1302                                 if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) {
1303                                         FLAC__metadata_object_delete(to);
1304                                         return 0;
1305                                 }
1306                                 break;
1307                         case FLAC__METADATA_TYPE_SEEKTABLE:
1308                                 to->data.seek_table.num_points = object->data.seek_table.num_points;
1309                                 if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetaData_SeekPoint))) {
1310                                         FLAC__metadata_object_delete(to);
1311                                         return 0;
1312                                 }
1313                                 break;
1314                         case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1315                                 if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) {
1316                                         FLAC__metadata_object_delete(to);
1317                                         return 0;
1318                                 }
1319                                 if(object->data.vorbis_comment.num_comments == 0) {
1320                                         FLAC__ASSERT(0 == object->data.vorbis_comment.comments);
1321                                         to->data.vorbis_comment.comments = 0;
1322                                 }
1323                                 else {
1324                                         FLAC__ASSERT(0 != object->data.vorbis_comment.comments);
1325                                         to->data.vorbis_comment.comments = FLAC__metadata_object_vorbiscomment_entry_array_copy(object->data.vorbis_comment.comments);
1326                                         if(0 == to->data.vorbis_comment.comments) {
1327                                                 FLAC__metadata_object_delete(to);
1328                                                 return 0;
1329                                         }
1330                                 }
1331                                 to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
1332                                 break;
1333                         default:
1334                                 /* double protection: */
1335                                 FLAC__ASSERT(0);
1336                                 free(to);
1337                                 return 0;
1338                 }
1339         }
1340
1341         return to;
1342 }
1343
1344 void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object)
1345 {
1346         unsigned i;
1347
1348         FLAC__ASSERT(0 != object);
1349
1350         switch(object->type) {
1351                 case FLAC__METADATA_TYPE_STREAMINFO:
1352                 case FLAC__METADATA_TYPE_PADDING:
1353                         break;
1354                 case FLAC__METADATA_TYPE_APPLICATION:
1355                         if(0 != object->data.application.data)
1356                                 free(object->data.application.data);
1357                         break;
1358                 case FLAC__METADATA_TYPE_SEEKTABLE:
1359                         if(0 != object->data.seek_table.points)
1360                                 free(object->data.seek_table.points);
1361                         break;
1362                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1363                         if(0 != object->data.vorbis_comment.vendor_string.entry)
1364                                 free(object->data.vorbis_comment.vendor_string.entry);
1365                         if(0 != object->data.vorbis_comment.comments) {
1366                                 FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0);
1367                                 FLAC__metadata_object_vorbiscomment_entry_array_delete(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
1368                         }
1369                         break;
1370                 default:
1371                         FLAC__ASSERT(0);
1372         }
1373 }
1374
1375 /*@@@@move
1376 frees 'object'.  does a deep delete.
1377 */
1378 void FLAC__metadata_object_delete(FLAC__StreamMetaData *object)
1379 {
1380         FLAC__metadata_object_delete_data_(object);
1381         free(object);
1382 }
1383
1384 /*@@@@move
1385 sets the application data to 'data'.  if 'copy' is true, makes, copy, else takes ownership of pointer.  returns false if copy==true and malloc fails.
1386     FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
1387     FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
1388 */
1389 FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetaData *object, FLAC__byte *data, unsigned length, FLAC__bool copy)
1390 {
1391         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
1392         FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
1393
1394         if(0 != object->data.application.data)
1395                 free(object->data.application.data);
1396
1397         if(copy) {
1398                 if(!copy_bytes_(&object->data.application.data, data, length))
1399                         return false;
1400         }
1401         else {
1402                 object->data.application.data = data;
1403         }
1404         object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8 + length;
1405         return true;
1406 }
1407
1408 /*@@@@move
1409 creates an array of seekpoints (FLAC__StreamMetaData_SeekPoint).  returns pointer to new array, or NULL if malloc fails.
1410 num_points > 0.
1411 */
1412 FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_new(unsigned num_points)
1413 {
1414         FLAC__StreamMetaData_SeekPoint *object_array;
1415
1416         FLAC__ASSERT(num_points > 0);
1417
1418         object_array = malloc(num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1419
1420         if(0 != object_array)
1421                 memset(object_array, 0, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1422
1423         return object_array;
1424 }
1425
1426 /*@@@@move
1427 return pointer to copy of seekpoint array, or NULL if malloc fails.
1428 num_points > 0
1429 object_array != NULL
1430 */
1431 FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_copy(const FLAC__StreamMetaData_SeekPoint *object_array, unsigned num_points)
1432 {
1433         FLAC__StreamMetaData_SeekPoint *return_array;
1434
1435         FLAC__ASSERT(0 != object_array);
1436         FLAC__ASSERT(num_points > 0);
1437
1438         return_array = FLAC__metadata_object_seekpoint_array_new(num_points);
1439
1440         if(0 != return_array)
1441                 memcpy(return_array, object_array, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1442
1443         return return_array;
1444 }
1445
1446 /*@@@@move
1447 frees object array.
1448 object_array != NULL
1449 */
1450 void FLAC__metadata_object_seekpoint_array_delete(FLAC__StreamMetaData_SeekPoint *object_array)
1451 {
1452         FLAC__ASSERT(0 != object_array);
1453
1454         free(object_array);
1455 }
1456
1457 FLAC__bool FLAC__metadata_object_seekpoint_array_resize(FLAC__StreamMetaData_SeekPoint **object_array, unsigned old_num_points, unsigned new_num_points)
1458 {
1459         FLAC__ASSERT(0 != object_array);
1460
1461         if(0 == *object_array) {
1462                 FLAC__ASSERT(old_num_points == 0);
1463                 if(0 == new_num_points)
1464                         return true;
1465                 else
1466                         return 0 != (*object_array = FLAC__metadata_object_seekpoint_array_new(new_num_points));
1467         }
1468         else {
1469                 const unsigned old_size = old_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
1470                 const unsigned new_size = new_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
1471
1472                 FLAC__ASSERT(old_num_points > 0);
1473
1474                 if(new_size == 0) {
1475                         free(*object_array);
1476                         *object_array = 0;
1477                 }
1478                 else if(0 == (*object_array = realloc(*object_array, new_size)))
1479                         return false;
1480
1481                 if(new_size > old_size)
1482                         memset(*object_array + old_num_points, 0, new_size - old_size);
1483
1484                 return true;
1485         }
1486 }
1487
1488 FLAC__bool FLAC__metadata_object_seektable_set_points(FLAC__StreamMetaData *object, FLAC__StreamMetaData_SeekPoint *points, unsigned num_points, FLAC__bool copy)
1489 {
1490         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
1491         FLAC__ASSERT((0 != points && num_points > 0) || (0 == points && num_points == 0 && copy == false));
1492
1493         object->data.seek_table.num_points = num_points;
1494
1495         if(0 != object->data.seek_table.points)
1496                 FLAC__metadata_object_seekpoint_array_delete(object->data.seek_table.points);
1497
1498         if(copy) {
1499                 if(0 == (object->data.seek_table.points = FLAC__metadata_object_seekpoint_array_copy(points, num_points)))
1500                         return false;
1501         }
1502         else {
1503                 object->data.seek_table.points = points;
1504         }
1505         object->length = num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1506         return true;
1507 }
1508
1509 FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_vorbiscomment_entry_array_new(unsigned num_comments)
1510 {
1511         FLAC__StreamMetaData_VorbisComment_Entry *object_array;
1512
1513         FLAC__ASSERT(num_comments > 0);
1514
1515         object_array = malloc(num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
1516
1517         if(0 != object_array)
1518                 memset(object_array, 0, num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
1519
1520         return object_array;
1521 }
1522
1523 FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_vorbiscomment_entry_array_copy(const FLAC__StreamMetaData_VorbisComment_Entry *object_array, unsigned num_comments)
1524 {
1525         FLAC__StreamMetaData_VorbisComment_Entry *return_array;
1526
1527         FLAC__ASSERT(0 != object_array);
1528         FLAC__ASSERT(num_comments > 0);
1529
1530         return_array = FLAC__metadata_object_vorbiscomment_entry_array_new(num_comments);
1531
1532         if(0 != return_array) {
1533                 unsigned i;
1534
1535                 /* Need to do this to set the pointers inside the comments to 0.
1536                  * In case of an error in the following loop, the object will be
1537                  * deleted and we don't want the destructor freeing uninitialized
1538                  * pointers.
1539                  */
1540                 memset(return_array, 0, num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
1541
1542                 for(i = 0; i < num_comments; i++) {
1543                         if(!copy_vcentry_(return_array+i, object_array+i)) {
1544                                 FLAC__metadata_object_vorbiscomment_entry_array_delete(return_array, num_comments);
1545                                 return 0;
1546                         }
1547                 }
1548         }
1549
1550         return return_array;
1551 }
1552
1553 void FLAC__metadata_object_vorbiscomment_entry_array_delete(FLAC__StreamMetaData_VorbisComment_Entry *object_array, unsigned num_comments)
1554 {
1555         unsigned i;
1556
1557         FLAC__ASSERT(0 != object_array && num_comments > 0);
1558
1559         for(i = 0; i < num_comments; i++)
1560                 if(0 != object_array[i].entry)
1561                         free(object_array[i].entry);
1562
1563         if(0 != object_array)
1564                 free(object_array);
1565 }
1566
1567 FLAC__bool FLAC__metadata_object_vorbiscomment_entry_array_resize(FLAC__StreamMetaData_VorbisComment_Entry **object_array, unsigned old_num_comments, unsigned new_num_comments)
1568 {
1569         FLAC__ASSERT(0 != object_array);
1570
1571         if(0 == *object_array) {
1572                 FLAC__ASSERT(old_num_comments == 0);
1573                 if(0 == new_num_comments)
1574                         return true;
1575                 else
1576                         return 0 != (*object_array = FLAC__metadata_object_vorbiscomment_entry_array_new(new_num_comments));
1577         }
1578         else {
1579                 const unsigned old_size = old_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
1580                 const unsigned new_size = new_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
1581
1582                 FLAC__ASSERT(old_num_comments > 0);
1583
1584                 /* if shrinking, free the truncated entries */
1585                 if(new_num_comments < old_num_comments) {
1586                         unsigned i;
1587                         for(i = new_num_comments; i < old_num_comments; i++)
1588                                 if(0 != (*object_array)[i].entry)
1589                                         free((*object_array)[i].entry);
1590                 }
1591
1592                 if(new_size == 0) {
1593                         free(*object_array);
1594                         *object_array = 0;
1595                 }
1596                 else if(0 == (*object_array = realloc(*object_array, new_size)))
1597                         return false;
1598
1599                 /* if growing, zero all the length/pointers of new elements */
1600                 if(new_size > old_size)
1601                         memset(*object_array + old_num_comments, 0, new_size - old_size);
1602
1603                 return true;
1604         }
1605 }
1606
1607 FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetaData *object, FLAC__byte *entry, unsigned length, FLAC__bool copy)
1608 {
1609         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
1610         FLAC__ASSERT((0 != entry && length > 0) || (0 == entry && length == 0 && copy == false));
1611
1612         if(0 != object->data.vorbis_comment.vendor_string.entry)
1613                 free(object->data.vorbis_comment.vendor_string.entry);
1614
1615         object->length -= object->data.vorbis_comment.vendor_string.length;
1616
1617         if(copy) {
1618                 if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, entry, length)) {
1619                         object->data.vorbis_comment.vendor_string.length = 0;
1620                         return false;
1621                 }
1622         }
1623         else {
1624                 object->data.vorbis_comment.vendor_string.entry = entry;
1625         }
1626
1627         object->data.vorbis_comment.vendor_string.length = length;
1628         object->length += object->data.vorbis_comment.vendor_string.length;
1629
1630         return true;
1631 }
1632
1633 FLAC__bool FLAC__metadata_object_vorbiscomment_set_comments(FLAC__StreamMetaData *object, FLAC__StreamMetaData_VorbisComment_Entry *comments, unsigned num_comments, FLAC__bool copy)
1634 {
1635         unsigned i;
1636
1637         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
1638         FLAC__ASSERT((0 != comments && num_comments > 0) || (0 == comments && num_comments == 0 && copy == false));
1639
1640         object->data.vorbis_comment.num_comments = num_comments;
1641
1642         if(0 != object->data.vorbis_comment.comments)
1643                 FLAC__metadata_object_vorbiscomment_entry_array_delete(object->data.vorbis_comment.comments, num_comments);
1644
1645         if(copy) {
1646                 if(0 == (object->data.vorbis_comment.comments = FLAC__metadata_object_vorbiscomment_entry_array_copy(comments, num_comments)))
1647                         return false;
1648         }
1649         else {
1650                 object->data.vorbis_comment.comments = comments;
1651         }
1652         object->length = num_comments * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1653
1654         /* calculate the new length */
1655         object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN) / 8;
1656         object->length += object->data.vorbis_comment.vendor_string.length;
1657         object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
1658         for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
1659                 object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8);
1660                 object->length += object->data.vorbis_comment.comments[i].length;
1661         }
1662
1663         return true;
1664 }
1665
1666 FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetaData *object, unsigned comment_num, FLAC__byte *entry, unsigned length, FLAC__bool copy)
1667 {
1668 }
1669
1670 FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetaData *object, unsigned comment_num, FLAC__byte *entry, unsigned length, FLAC__bool copy)
1671 {
1672 }
1673
1674 FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetaData *object, unsigned comment_num)
1675 {
1676 }
1677
1678
1679 /****************************************************************************
1680  *
1681  * Local function definitions
1682  *
1683  ***************************************************************************/
1684
1685 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1686 {
1687         unsigned i;
1688
1689         b += bytes;
1690
1691         for(i = 0; i < bytes; i++) {
1692                 *(--b) = (FLAC__byte)(val & 0xff);
1693                 val >>= 8;
1694         }
1695 }
1696
1697 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1698 {
1699         unsigned i;
1700
1701         for(i = 0; i < bytes; i++) {
1702                 *(b++) = (FLAC__byte)(val & 0xff);
1703                 val >>= 8;
1704         }
1705 }
1706
1707 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes)
1708 {
1709         unsigned i;
1710
1711         b += bytes;
1712
1713         for(i = 0; i < bytes; i++) {
1714                 *(--b) = (FLAC__byte)(val & 0xff);
1715                 val >>= 8;
1716         }
1717 }
1718
1719 FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes)
1720 {
1721         FLAC__uint32 ret = 0;
1722         unsigned i;
1723
1724         for(i = 0; i < bytes; i++)
1725                 ret = (ret << 8) | (FLAC__uint32)(*b++);
1726
1727         return ret;
1728 }
1729
1730 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes)
1731 {
1732         FLAC__uint32 ret = 0;
1733         unsigned i;
1734
1735         b += bytes;
1736
1737         for(i = 0; i < bytes; i++)
1738                 ret = (ret << 8) | (FLAC__uint32)(*--b);
1739
1740         return ret;
1741 }
1742
1743 FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes)
1744 {
1745         FLAC__uint64 ret = 0;
1746         unsigned i;
1747
1748         for(i = 0; i < bytes; i++)
1749                 ret = (ret << 8) | (FLAC__uint64)(*b++);
1750
1751         return ret;
1752 }
1753
1754 FLAC__bool read_metadata_block_header_(FLAC__MetaData_SimpleIterator *iterator)
1755 {
1756         FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
1757
1758         FLAC__ASSERT(0 != iterator);
1759         FLAC__ASSERT(0 != iterator->file);
1760
1761         if(fread(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, iterator->file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1762                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1763                 return false;
1764         }
1765
1766         iterator->is_last = raw_header[0] & 0x80? true : false;
1767         iterator->type = (FLAC__MetaDataType)(raw_header[0] & 0x7f);
1768         iterator->length = unpack_uint32_(raw_header + 1, 3);
1769
1770         /* do some checking */
1771         if(iterator->type > FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1772                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
1773                 return false;
1774         }
1775
1776         return true;
1777 }
1778
1779 FLAC__bool read_metadata_block_data_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block)
1780 {
1781         FLAC__ASSERT(0 != iterator);
1782         FLAC__ASSERT(0 != iterator->file);
1783
1784         switch(block->type) {
1785                 case FLAC__METADATA_TYPE_STREAMINFO:
1786                         iterator->status = read_metadata_block_data_streaminfo_(iterator->file, &block->data.stream_info);
1787                         break;
1788                 case FLAC__METADATA_TYPE_PADDING:
1789                         iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length);
1790                         break;
1791                 case FLAC__METADATA_TYPE_APPLICATION:
1792                         iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length);
1793                         break;
1794                 case FLAC__METADATA_TYPE_SEEKTABLE:
1795                         iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length);
1796                         break;
1797                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1798                         iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment);
1799                         break;
1800                 default:
1801                         FLAC__ASSERT(0);
1802                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1803         }
1804
1805         return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1806 }
1807
1808 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetaData_StreamInfo *block)
1809 {
1810         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
1811
1812         FLAC__ASSERT(0 != file);
1813
1814         if(fread(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1815                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1816
1817         b = buffer;
1818
1819         /* @@@ we are using hardcoded numbers for simplicity but we should
1820          * probably eventually write a bit-level unpacker and use the
1821          * _STREAMINFO_ constants.
1822          */
1823         block->min_blocksize = unpack_uint32_(b, 2); b += 2;
1824         block->max_blocksize = unpack_uint32_(b, 2); b += 2;
1825         block->min_framesize = unpack_uint32_(b, 3); b += 3;
1826         block->max_framesize = unpack_uint32_(b, 3); b += 3;
1827         block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
1828         block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
1829         block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 1) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
1830         block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
1831         memcpy(block->md5sum, b+8, 16);
1832
1833         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1834 }
1835
1836
1837 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetaData_Padding *block, unsigned block_length)
1838 {
1839         FLAC__ASSERT(0 != file);
1840
1841         (void)block; /* nothing to do; we don't care about reading the padding bytes */
1842
1843         if(0 != fseek(file, block_length, SEEK_CUR))
1844                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1845
1846         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1847 }
1848
1849 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetaData_Application *block, unsigned block_length)
1850 {
1851         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1852
1853         FLAC__ASSERT(0 != file);
1854
1855         if(fread(block->id, 1, id_bytes, file) != id_bytes)
1856                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1857
1858         block_length -= id_bytes;
1859
1860         if(block_length == 0) {
1861                 block->data = 0;
1862         }
1863         else {
1864                 if(0 == (block->data = malloc(block_length)))
1865                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1866
1867                 if(fread(block->data, 1, block_length, file) != block_length)
1868                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1869         }
1870
1871         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1872 }
1873
1874 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetaData_SeekTable *block, unsigned block_length)
1875 {
1876         unsigned i;
1877         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1878
1879         FLAC__ASSERT(0 != file);
1880         FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0);
1881
1882         block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1883
1884         if(block->num_points == 0)
1885                 block->points = 0;
1886         else if(0 == (block->points = malloc(block->num_points * sizeof(FLAC__StreamMetaData_SeekPoint))))
1887                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1888
1889         for(i = 0; i < block->num_points; i++) {
1890                 if(fread(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1891                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1892                 /*@@@ some MAGIC NUMBERs here */
1893                 block->points[i].sample_number = unpack_uint64_(buffer, 8);
1894                 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
1895                 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
1896         }
1897
1898         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1899 }
1900
1901 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetaData_VorbisComment_Entry *entry)
1902 {
1903         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1904         FLAC__byte buffer[FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8];
1905
1906         FLAC__ASSERT(0 != file);
1907
1908         if(fread(buffer, 1, entry_length_len, file) != entry_length_len)
1909                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1910         entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
1911
1912         if(entry->length == 0) {
1913                 entry->entry = 0;
1914         }
1915         else {
1916                 if(0 == (entry->entry = malloc(entry->length)))
1917                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1918
1919                 if(fread(entry->entry, 1, entry->length, file) != entry->length)
1920                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1921         }
1922
1923         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1924 }
1925
1926 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetaData_VorbisComment *block)
1927 {
1928         unsigned i;
1929         FLAC__MetaData_SimpleIteratorStatus status;
1930         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1931         FLAC__byte buffer[FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8];
1932
1933         FLAC__ASSERT(0 != file);
1934
1935         if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, &(block->vendor_string))))
1936                 return status;
1937
1938         if(fread(buffer, 1, num_comments_len, file) != num_comments_len)
1939                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1940         block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
1941
1942         if(block->num_comments == 0) {
1943                 block->comments = 0;
1944         }
1945         else if(0 == (block->comments = malloc(block->num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry))))
1946                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1947
1948         for(i = 0; i < block->num_comments; i++) {
1949                 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, block->comments + i)))
1950                         return status;
1951         }
1952
1953         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1954 }
1955
1956 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block)
1957 {
1958         FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
1959
1960         FLAC__ASSERT(0 != file);
1961         FLAC__ASSERT(0 != status);
1962         FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
1963
1964         buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type;
1965         pack_uint32_(block->length, buffer + 1, 3);
1966
1967         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1968                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1969                 return false;
1970         }
1971
1972         return true;
1973 }
1974
1975 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block)
1976 {
1977         FLAC__ASSERT(0 != file);
1978         FLAC__ASSERT(0 != status);
1979
1980         switch(block->type) {
1981                 case FLAC__METADATA_TYPE_STREAMINFO:
1982                         *status = write_metadata_block_data_streaminfo_(file, &block->data.stream_info);
1983                         break;
1984                 case FLAC__METADATA_TYPE_PADDING:
1985                         *status = write_metadata_block_data_padding_(file, &block->data.padding, block->length);
1986                         break;
1987                 case FLAC__METADATA_TYPE_APPLICATION:
1988                         *status = write_metadata_block_data_application_(file, &block->data.application, block->length);
1989                         break;
1990                 case FLAC__METADATA_TYPE_SEEKTABLE:
1991                         *status = write_metadata_block_data_seektable_(file, &block->data.seek_table);
1992                         break;
1993                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1994                         *status = write_metadata_block_data_vorbis_comment_(file, &block->data.vorbis_comment);
1995                         break;
1996                 default:
1997                         FLAC__ASSERT(0);
1998                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1999         }
2000         return (*status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
2001 }
2002
2003 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetaData_StreamInfo *block)
2004 {
2005         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
2006         const unsigned channels1 = block->channels - 1;
2007         const unsigned bps1 = block->bits_per_sample - 1;
2008
2009         FLAC__ASSERT(0 != file);
2010
2011         /* @@@ we are using hardcoded numbers for simplicity but we should
2012          * probably eventually write a bit-level packer and use the
2013          * _STREAMINFO_ constants.
2014          */
2015         pack_uint32_(block->min_blocksize, buffer, 2);
2016         pack_uint32_(block->max_blocksize, buffer+2, 2);
2017         pack_uint32_(block->min_framesize, buffer+4, 3);
2018         pack_uint32_(block->max_framesize, buffer+7, 3);
2019         buffer[10] = (block->sample_rate >> 12) & 0xff;
2020         buffer[11] = (block->sample_rate >> 4) & 0xff;
2021         buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4);
2022         buffer[13] = ((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f);
2023         pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4);
2024         memcpy(buffer+18, block->md5sum, 16);
2025
2026         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
2027                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2028
2029         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2030 }
2031
2032 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetaData_Padding *block, unsigned block_length)
2033 {
2034         unsigned i, n = block_length;
2035         FLAC__byte buffer[1024];
2036
2037         FLAC__ASSERT(0 != file);
2038
2039         (void)block;
2040
2041         memset(buffer, 0, 1024);
2042
2043         for(i = 0; i < n/1024; i++)
2044                 if(fwrite(buffer, 1, 1024, file) != 1024)
2045                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2046
2047         n %= 1024;
2048         
2049         if(fwrite(buffer, 1, n, file) != n)
2050                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2051
2052         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2053 }
2054
2055 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetaData_Application *block, unsigned block_length)
2056 {
2057         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
2058
2059         FLAC__ASSERT(0 != file);
2060
2061         if(fwrite(block->id, 1, id_bytes, file) != id_bytes)
2062                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2063
2064         block_length -= id_bytes;
2065
2066         if(fwrite(block->data, 1, block_length, file) != block_length)
2067                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2068
2069         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2070 }
2071
2072 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetaData_SeekTable *block)
2073 {
2074         unsigned i;
2075         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
2076
2077         FLAC__ASSERT(0 != file);
2078
2079         for(i = 0; i < block->num_points; i++) {
2080                 /*@@@ some MAGIC NUMBERs here */
2081                 pack_uint64_(block->points[i].sample_number, buffer, 8);
2082                 pack_uint64_(block->points[i].stream_offset, buffer+8, 8);
2083                 pack_uint32_(block->points[i].frame_samples, buffer+16, 2);
2084                 if(fwrite(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
2085                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2086         }
2087
2088         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2089 }
2090
2091 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetaData_VorbisComment *block)
2092 {
2093         unsigned i;
2094         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
2095         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2096         FLAC__byte buffer[max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8];
2097
2098         FLAC__ASSERT(0 != file);
2099
2100         pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
2101         if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
2102                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2103         if(fwrite(block->vendor_string.entry, 1, block->vendor_string.length, file) != block->vendor_string.length)
2104                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2105
2106         pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len);
2107         if(fwrite(buffer, 1, num_comments_len, file) != num_comments_len)
2108                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2109
2110         for(i = 0; i < block->num_comments; i++) {
2111                 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len);
2112                 if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
2113                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2114                 if(fwrite(block->comments[i].entry, 1, block->comments[i].length, file) != block->comments[i].length)
2115                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2116         }
2117
2118         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2119 }
2120
2121 FLAC__bool write_metadata_block_stationary_(FLAC__MetaData_SimpleIterator *iterator, const FLAC__StreamMetaData *block)
2122 {
2123         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2124                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2125                 return false;
2126         }
2127
2128         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
2129                 return false;
2130
2131         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
2132                 return false;
2133
2134         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2135                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2136                 return false;
2137         }
2138
2139         return read_metadata_block_header_(iterator);
2140 }
2141
2142 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, unsigned padding_length, FLAC__bool padding_is_last)
2143 {
2144         FLAC__StreamMetaData *padding;
2145
2146         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2147                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2148                 return false;
2149         }
2150
2151         block->is_last = false;
2152
2153         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
2154                 return false;
2155
2156         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
2157                 return false;
2158
2159         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
2160                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2161
2162         padding->is_last = padding_is_last;
2163         padding->length = padding_length;
2164
2165         if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) {
2166                 FLAC__metadata_object_delete(padding);
2167                 return false;
2168         }
2169
2170         if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) {
2171                 FLAC__metadata_object_delete(padding);
2172                 return false;
2173         }
2174
2175         FLAC__metadata_object_delete(padding);
2176
2177         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2178                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2179                 return false;
2180         }
2181
2182         return read_metadata_block_header_(iterator);
2183 }
2184
2185 FLAC__bool rewrite_whole_file_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool append)
2186 {
2187         FILE *tempfile;
2188         char *tempfilename;
2189         int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
2190         long fixup_is_last_flag_offset = -1;
2191
2192         FLAC__ASSERT(0 != block || append == false);
2193
2194         if(iterator->is_last) {
2195                 if(append) {
2196                         fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */
2197                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
2198                 }
2199                 else if(0 == block) {
2200                         simple_iterator_push_(iterator);
2201                         if(!FLAC__metadata_simple_iterator_prev(iterator)) {
2202                                 (void)simple_iterator_pop_(iterator);
2203                                 return false;
2204                         }
2205                         fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */
2206                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
2207                         if(!simple_iterator_pop_(iterator))
2208                                 return false;
2209                 }
2210         }
2211
2212         if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append))
2213                 return false;
2214
2215         if(0 != block) {
2216                 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) {
2217                         cleanup_tempfile_(&tempfile, &tempfilename);
2218                         return false;
2219                 }
2220
2221                 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) {
2222                         cleanup_tempfile_(&tempfile, &tempfilename);
2223                         return false;
2224                 }
2225         }
2226
2227         if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0))
2228                 return false;
2229
2230         if(append)
2231                 return FLAC__metadata_simple_iterator_next(iterator);
2232
2233         return true;
2234 }
2235
2236 FLAC__bool chain_rewrite_chain_(FLAC__MetaData_Chain *chain)
2237 {
2238         FILE *f;
2239         FLAC__MetaData_Node *node;
2240         FLAC__MetaData_SimpleIteratorStatus status;
2241
2242         FLAC__ASSERT(0 != chain);
2243         FLAC__ASSERT(0 != chain->filename);
2244         FLAC__ASSERT(0 != chain->head);
2245
2246         if(0 == (f = fopen(chain->filename, "r+b"))) {
2247                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2248                 return false;
2249         }
2250         if(0 != fseek(f, chain->first_offset, SEEK_SET)) {
2251                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2252                 return false;
2253         }
2254
2255         for(node = chain->head; node; node = node->next) {
2256                 if(!write_metadata_block_header_(f, &status, node->data)) {
2257                         chain->status = get_equivalent_status_(status);
2258                         return false;
2259                 }
2260                 if(!write_metadata_block_data_(f, &status, node->data)) {
2261                         chain->status = get_equivalent_status_(status);
2262                         return false;
2263                 }
2264         }
2265
2266         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
2267
2268         (void)fclose(f);
2269
2270         return true;
2271 }
2272
2273 FLAC__bool chain_rewrite_file_(FLAC__MetaData_Chain *chain, const char *tempfile_path_prefix)
2274 {
2275         FILE *f, *tempfile;
2276         char *tempfilename;
2277         FLAC__MetaData_SimpleIteratorStatus status;
2278         const FLAC__MetaData_Node *node;
2279
2280         FLAC__ASSERT(0 != chain);
2281         FLAC__ASSERT(0 != chain->filename);
2282         FLAC__ASSERT(0 != chain->head);
2283
2284         /* copy the file prefix (data up to first metadata block */
2285         if(0 == (f = fopen(chain->filename, "rb"))) {
2286                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2287                 return false;
2288         }
2289         if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) {
2290                 chain->status = get_equivalent_status_(status);
2291                 cleanup_tempfile_(&tempfile, &tempfilename);
2292                 return false;
2293         }
2294         if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) {
2295                 chain->status = get_equivalent_status_(status);
2296                 cleanup_tempfile_(&tempfile, &tempfilename);
2297                 return false;
2298         }
2299
2300         /* write the metadata */
2301         for(node = chain->head; node; node = node->next) {
2302                 if(!write_metadata_block_header_(tempfile, &status, node->data)) {
2303                         chain->status = get_equivalent_status_(status);
2304                         return false;
2305                 }
2306                 if(!write_metadata_block_data_(tempfile, &status, node->data)) {
2307                         chain->status = get_equivalent_status_(status);
2308                         return false;
2309                 }
2310         }
2311         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
2312
2313         /* copy the file postfix (everything after the metadata) */
2314         if(0 != fseek(f, chain->last_offset, SEEK_SET)) {
2315                 cleanup_tempfile_(&tempfile, &tempfilename);
2316                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2317                 return false;
2318         }
2319         if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) {
2320                 cleanup_tempfile_(&tempfile, &tempfilename);
2321                 chain->status = get_equivalent_status_(status);
2322                 return false;
2323         }
2324
2325         /* move the tempfile on top of the original */
2326         (void)fclose(f);
2327         if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
2328                 return false;
2329
2330         return true;
2331 }
2332
2333 void simple_iterator_push_(FLAC__MetaData_SimpleIterator *iterator)
2334 {
2335         FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH);
2336         iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth];
2337         iterator->depth++;
2338 }
2339
2340 FLAC__bool simple_iterator_pop_(FLAC__MetaData_SimpleIterator *iterator)
2341 {
2342         FLAC__ASSERT(iterator->depth > 0);
2343         iterator->depth--;
2344         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2345                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2346                 return false;
2347         }
2348
2349         return read_metadata_block_header_(iterator);
2350 }
2351
2352 unsigned seek_to_first_metadata_block_(FILE *f)
2353 {
2354         FLAC__byte buffer[4];
2355         size_t n;
2356         unsigned i;
2357
2358         FLAC__ASSERT(0 != f);
2359         FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
2360
2361         /* skip any id3v2 tag */
2362         errno = 0;
2363         n = fread(buffer, 1, 4, f);
2364         if(errno)
2365                 return 1;
2366         else if(n != 4)
2367                 return 2;
2368         else if(0 == memcmp(buffer, "ID3", 3)) {
2369                 unsigned tag_length = 0;
2370
2371                 /* skip to the tag length */
2372                 if(fseek(f, 2, SEEK_CUR) < 0)
2373                         return 1;
2374
2375                 /* read the length */
2376                 for(i = 0; i < 4; i++) {
2377                         if(fread(buffer, 1, 1, f) < 1 || buffer[0] & 0x80)
2378                                 return 1;
2379                         tag_length <<= 7;
2380                         tag_length |= (buffer[0] & 0x7f);
2381                 }
2382
2383                 /* skip the rest of the tag */
2384                 if(fseek(f, tag_length, SEEK_CUR) < 0)
2385                         return 1;
2386
2387                 /* read the stream sync code */
2388                 errno = 0;
2389                 n = fread(buffer, 1, 4, f);
2390                 if(errno)
2391                         return 1;
2392                 else if(n != 4)
2393                         return 2;
2394         }
2395
2396         /* check for the fLaC signature */
2397         if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH))
2398                 return 0;
2399         else
2400                 return 2;
2401 }
2402
2403 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
2404 {
2405         const long offset_end = append? iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length : iterator->offset[iterator->depth];
2406
2407         if(0 != fseek(iterator->file, 0, SEEK_SET)) {
2408                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2409                 return false;
2410         }
2411         if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) {
2412                 cleanup_tempfile_(tempfile, tempfilename);
2413                 return false;
2414         }
2415         if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) {
2416                 cleanup_tempfile_(tempfile, tempfilename);
2417                 return false;
2418         }
2419
2420         return true;
2421 }
2422
2423 FLAC__bool simple_iterator_copy_file_postfix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, long fixup_is_last_flag_offset, FLAC__bool backup)
2424 {
2425         long save_offset = iterator->offset[iterator->depth]; /*@@@ 2G limit */
2426         FLAC__ASSERT(0 != *tempfile);
2427
2428         if(0 != fseek(iterator->file, save_offset + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length, SEEK_SET)) {
2429                 cleanup_tempfile_(tempfile, tempfilename);
2430                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2431                 return false;
2432         }
2433         if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) {
2434                 cleanup_tempfile_(tempfile, tempfilename);
2435                 return false;
2436         }
2437
2438         if(fixup_is_last_code != 0) {
2439                 /*
2440                  * if code == 1, it means a block was appended to the end so
2441                  *   we have to clear the is_last flag of the previous block
2442                  * if code == -1, it means the last block was deleted so
2443                  *   we have to set the is_last flag of the previous block
2444                  */
2445                 /*@@@ MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
2446                 FLAC__byte x;
2447                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2448                         cleanup_tempfile_(tempfile, tempfilename);
2449                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2450                         return false;
2451                 }
2452                 if(fread(&x, 1, 1, *tempfile) != 1) {
2453                         cleanup_tempfile_(tempfile, tempfilename);
2454                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2455                         return false;
2456                 }
2457                 if(fixup_is_last_code > 0) {
2458                         FLAC__ASSERT(x & 0x80);
2459                         x &= 0x7f;
2460                 }
2461                 else {
2462                         FLAC__ASSERT(!(x & 0x80));
2463                         x |= 0x80;
2464                 }
2465                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2466                         cleanup_tempfile_(tempfile, tempfilename);
2467                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2468                         return false;
2469                 }
2470                 if(fwrite(&x, 1, 1, *tempfile) != 1) {
2471                         cleanup_tempfile_(tempfile, tempfilename);
2472                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2473                         return false;
2474                 }
2475         }
2476
2477         (void)fclose(iterator->file);
2478
2479         if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status))
2480                 return false;
2481
2482         if(iterator->has_stats)
2483                 set_file_stats_(iterator->filename, &iterator->stats);
2484
2485         if(!simple_iterator_prime_input_(iterator))
2486                 return false;
2487         if(backup) {
2488                 while(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length < save_offset)
2489                         if(!FLAC__metadata_simple_iterator_next(iterator))
2490                                 return false;
2491                 return true;
2492         }
2493         else {
2494                 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */
2495                 FLAC__ASSERT(iterator->depth == 0);
2496                 iterator->offset[0] = save_offset;
2497                 iterator->depth++;
2498                 return simple_iterator_pop_(iterator);
2499         }
2500 }
2501
2502 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__MetaData_SimpleIteratorStatus *status)
2503 {
2504         FLAC__byte buffer[8192];
2505         unsigned n;
2506
2507         while(bytes > 0) {
2508                 n = min(sizeof(buffer), bytes);
2509                 if(fread(buffer, 1, n, file) != n) {
2510                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2511                         return false;
2512                 }
2513                 if(fwrite(buffer, 1, n, tempfile) != n) {
2514                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2515                         return false;
2516                 }
2517                 bytes -= n;
2518         }
2519
2520         return true;
2521 }
2522
2523 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__MetaData_SimpleIteratorStatus *status)
2524 {
2525         FLAC__byte buffer[8192];
2526         size_t n;
2527
2528         while(!feof(file)) {
2529                 n = fread(buffer, 1, sizeof(buffer), file);
2530                 if(n == 0 && !feof(file)) {
2531                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2532                         return false;
2533                 }
2534                 if(n > 0 && fwrite(buffer, 1, n, tempfile) != n) {
2535                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2536                         return false;
2537                 }
2538         }
2539
2540         return true;
2541 }
2542
2543 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status)
2544 {
2545         static const char *tempfile_suffix = ".metadata_edit";
2546         if(0 == tempfile_path_prefix) {
2547                 if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) {
2548                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2549                         return false;
2550                 }
2551                 strcpy(*tempfilename, filename);
2552                 strcat(*tempfilename, tempfile_suffix);
2553         }
2554         else {
2555                 const char *p = strrchr(filename, '/');
2556                 if(0 == p)
2557                         p = filename;
2558                 else
2559                         p++;
2560
2561                 if(0 == (*tempfilename = malloc(strlen(tempfile_path_prefix) + 1 + strlen(p) + strlen(tempfile_suffix) + 1))) {
2562                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2563                         return false;
2564                 }
2565                 strcpy(*tempfilename, tempfile_path_prefix);
2566                 strcat(*tempfilename, "/");
2567                 strcat(*tempfilename, p);
2568                 strcat(*tempfilename, tempfile_suffix);
2569         }
2570
2571         if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) {
2572                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
2573                 return false;
2574         }
2575
2576         return true;
2577 }
2578
2579 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status)
2580 {
2581         FLAC__ASSERT(0 != filename);
2582         FLAC__ASSERT(0 != tempfile);
2583         FLAC__ASSERT(0 != *tempfile);
2584         FLAC__ASSERT(0 != tempfilename);
2585         FLAC__ASSERT(0 != *tempfilename);
2586         FLAC__ASSERT(0 != status);
2587
2588         (void)fclose(*tempfile);
2589         *tempfile = 0;
2590         /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */
2591         if(0 != rename(*tempfilename, filename)) {
2592                 cleanup_tempfile_(tempfile, tempfilename);
2593                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
2594                 return false;
2595         }
2596
2597         cleanup_tempfile_(tempfile, tempfilename);
2598
2599         return true;
2600 }
2601
2602 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
2603 {
2604         if(0 != *tempfile) {
2605                 (void)fclose(*tempfile);
2606                 *tempfile = 0;
2607         }
2608
2609         if(0 != *tempfilename) {
2610                 (void)unlink(*tempfilename);
2611                 free(*tempfilename);
2612                 *tempfilename = 0;
2613         }
2614 }
2615
2616 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
2617 {
2618         FLAC__ASSERT(0 != filename);
2619         FLAC__ASSERT(0 != stats);
2620         return (0 == stat(filename, stats));
2621 }
2622
2623 void set_file_stats_(const char *filename, struct stat *stats)
2624 {
2625         struct utimbuf srctime;
2626
2627         FLAC__ASSERT(0 != filename);
2628         FLAC__ASSERT(0 != stats);
2629
2630         srctime.actime = stats->st_atime;
2631         srctime.modtime = stats->st_mtime;
2632         (void)chmod(filename, stats->st_mode);
2633         (void)utime(filename, &srctime);
2634 #if !defined _MSC_VER && !defined __MINGW32__
2635         (void)chown(filename, stats->st_uid, -1);
2636         (void)chown(filename, -1, stats->st_gid);
2637 #endif
2638 }
2639
2640 FLAC__MetaData_ChainStatus get_equivalent_status_(FLAC__MetaData_SimpleIteratorStatus status)
2641 {
2642         switch(status) {
2643                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK:
2644                         return FLAC__METADATA_CHAIN_STATUS_OK;
2645                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
2646                         return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT;
2647                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
2648                         return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2649                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
2650                         return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
2651                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE:
2652                         return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE;
2653                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA:
2654                         return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
2655                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR:
2656                         return FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
2657                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR:
2658                         return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2659                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR:
2660                         return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
2661                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR:
2662                         return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR;
2663                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR:
2664                         return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR;
2665                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR:
2666                         return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
2667                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR:
2668                 default:
2669                         return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
2670         }
2671 }