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