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