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