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