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