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