fixes from compiling code and running all the tests on NT
[platform/upstream/flac.git] / src / libFLAC / metadata_iterators.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2001,2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 #else
29 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
30 #include <utime.h> /* for utime() */
31 #include <unistd.h> /* for chown(), unlink() */
32 #endif
33 #include <sys/stat.h> /* for stat(), maybe chmod() */
34
35 #include "private/metadata.h"
36
37 #include "FLAC/assert.h"
38 #include "FLAC/file_decoder.h"
39
40 #ifdef max
41 #undef max
42 #endif
43 #define max(a,b) ((a)>(b)?(a):(b))
44 #ifdef min
45 #undef min
46 #endif
47 #define min(a,b) ((a)<(b)?(a):(b))
48
49
50 /****************************************************************************
51  *
52  * Local function declarations
53  *
54  ***************************************************************************/
55
56 static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
57 static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
58 static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes);
59 static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes);
60 static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes);
61 static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes);
62
63 static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator);
64 static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block);
65 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block);
66 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetadata_Padding *block, unsigned block_length);
67 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetadata_Application *block, unsigned block_length);
68 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetadata_SeekTable *block, unsigned block_length);
69 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetadata_VorbisComment_Entry *entry);
70 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block);
71
72 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
73 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
74 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetadata_StreamInfo *block);
75 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetadata_Padding *block, unsigned block_length);
76 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetadata_Application *block, unsigned block_length);
77 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetadata_SeekTable *block);
78 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetadata_VorbisComment *block);
79 static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
80 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last);
81 static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append);
82
83 static FLAC__bool chain_rewrite_chain_(FLAC__Metadata_Chain *chain);
84 static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix);
85
86 static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator);
87 static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator);
88
89 /* return 0 if OK, 1 if read error, 2 if not a FLAC file */
90 static unsigned seek_to_first_metadata_block_(FILE *f);
91
92 static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append);
93 static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, long fixup_is_last_flag_offset, FLAC__bool backup);
94
95 static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status);
96 static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status);
97
98 static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
99 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
100 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename);
101
102 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats);
103 static void set_file_stats_(const char *filename, struct stat *stats);
104
105 static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status);
106
107
108 /****************************************************************************
109  *
110  * Level 0 implementation
111  *
112  ***************************************************************************/
113
114 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
115 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
116 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
117
118 typedef struct {
119         FLAC__bool got_error;
120         FLAC__bool got_streaminfo;
121         FLAC__StreamMetadata *streaminfo;
122 } level0_client_data;
123
124 FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
125 {
126         level0_client_data cd;
127         FLAC__FileDecoder *decoder = FLAC__file_decoder_new();
128
129         if(0 == decoder)
130                 return false;
131
132         cd.got_error = false;
133         cd.got_streaminfo = false;
134         cd.streaminfo = streaminfo;
135
136         FLAC__file_decoder_set_md5_checking(decoder, false);
137         FLAC__file_decoder_set_filename(decoder, filename);
138         FLAC__file_decoder_set_write_callback(decoder, write_callback_);
139         FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
140         FLAC__file_decoder_set_error_callback(decoder, error_callback_);
141         FLAC__file_decoder_set_client_data(decoder, &cd);
142
143         if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
144                 FLAC__file_decoder_finish(decoder);
145                 FLAC__file_decoder_delete(decoder);
146                 return false;
147         }
148
149         if(!FLAC__file_decoder_process_metadata(decoder) || cd.got_error) {
150                 FLAC__file_decoder_finish(decoder);
151                 FLAC__file_decoder_delete(decoder);
152                 return false;
153         }
154
155         FLAC__file_decoder_finish(decoder);
156         FLAC__file_decoder_delete(decoder);
157
158         return !cd.got_error && cd.got_streaminfo;
159 }
160
161 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
162 {
163         (void)decoder, (void)frame, (void)buffer, (void)client_data;
164
165         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
166 }
167
168 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
169 {
170         level0_client_data *cd = (level0_client_data *)client_data;
171         (void)decoder;
172
173         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && 0 != cd->streaminfo) {
174                 *(cd->streaminfo) = *metadata;
175                 cd->got_streaminfo = true;
176         }
177 }
178
179 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
180 {
181         level0_client_data *cd = (level0_client_data *)client_data;
182         (void)decoder;
183
184         if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
185                 cd->got_error = true;
186 }
187
188
189 /****************************************************************************
190  *
191  * Level 1 implementation
192  *
193  ***************************************************************************/
194
195 #define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4)
196 /* 1 for initial offset, +4 for our own personal use */
197
198 struct FLAC__Metadata_SimpleIterator {
199         FILE *file;
200         char *filename, *tempfile_path_prefix;
201         struct stat stats;
202         FLAC__bool has_stats;
203         FLAC__bool is_writable;
204         FLAC__Metadata_SimpleIteratorStatus status;
205         /*@@@ 2G limits here because of the offset type: */
206         long offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
207         long first_offset; /* this is the offset to the STREAMINFO block */
208         unsigned depth;
209         /* this is the metadata block header of the current block we are pointing to: */
210         FLAC__bool is_last;
211         FLAC__MetadataType type;
212         unsigned length;
213 };
214
215 const char * const FLAC__Metadata_SimpleIteratorStatusString[] = {
216         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK",
217         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT",
218         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE",
219         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE",
220         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE",
221         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA",
222         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR",
223         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR",
224         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR",
225         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR",
226         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR",
227         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR",
228         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR"
229 };
230
231
232 FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new()
233 {
234         FLAC__Metadata_SimpleIterator *iterator = malloc(sizeof(FLAC__Metadata_SimpleIterator));
235
236         if(0 != iterator) {
237                 iterator->file = 0;
238                 iterator->filename = 0;
239                 iterator->tempfile_path_prefix = 0;
240                 iterator->has_stats = false;
241                 iterator->is_writable = false;
242                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
243                 iterator->first_offset = iterator->offset[0] = -1;
244                 iterator->depth = 0;
245         }
246
247         return iterator;
248 }
249
250 static void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator)
251 {
252         FLAC__ASSERT(0 != iterator);
253
254         if(0 != iterator->file) {
255                 fclose(iterator->file);
256                 iterator->file = 0;
257                 if(iterator->has_stats)
258                         set_file_stats_(iterator->filename, &iterator->stats);
259         }
260         if(0 != iterator->filename) {
261                 free(iterator->filename);
262                 iterator->filename = 0;
263         }
264         if(0 != iterator->tempfile_path_prefix) {
265                 free(iterator->tempfile_path_prefix);
266                 iterator->tempfile_path_prefix = 0;
267         }
268 }
269
270 void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator)
271 {
272         FLAC__ASSERT(0 != iterator);
273
274         simple_iterator_free_guts_(iterator);
275         free(iterator);
276 }
277
278 FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator)
279 {
280         FLAC__Metadata_SimpleIteratorStatus status;
281
282         FLAC__ASSERT(0 != iterator);
283
284         status = iterator->status;
285         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
286         return status;
287 }
288
289 static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator)
290 {
291         unsigned ret;
292
293         FLAC__ASSERT(0 != iterator);
294
295         iterator->is_writable = false;
296
297         if(0 == (iterator->file = fopen(iterator->filename, "r+b"))) {
298                 if(errno == EACCES) {
299                         if(0 == (iterator->file = fopen(iterator->filename, "rb"))) {
300                                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
301                                 return false;
302                         }
303                 }
304                 else {
305                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
306                         return false;
307                 }
308         }
309         else {
310                 iterator->is_writable = true;
311         }
312
313         ret = seek_to_first_metadata_block_(iterator->file);
314         switch(ret) {
315                 case 0:
316                         iterator->depth = 0;
317                         iterator->first_offset = iterator->offset[iterator->depth] = ftell(iterator->file);
318                         return read_metadata_block_header_(iterator);
319                 case 1:
320                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
321                         return false;
322                 case 2:
323                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE;
324                         return false;
325                 default:
326                         FLAC__ASSERT(0);
327                         return false;
328         }
329 }
330
331 #if 0
332 @@@ If we decide to finish implementing this, put this comment back in metadata.h
333 /*
334  * The 'tempfile_path_prefix' allows you to specify a directory where
335  * tempfiles should go.  Remember that if your metadata edits cause the
336  * FLAC file to grow, the entire file will have to be rewritten.  If
337  * 'tempfile_path_prefix' is NULL, the temp file will be written in the
338  * same directory as the original FLAC file.  This makes replacing the
339  * original with the tempfile fast but requires extra space in the same
340  * partition for the tempfile.  If space is a problem, you can pass a
341  * directory name belonging to a different partition in
342  * 'tempfile_path_prefix'.  Note that you should use the forward slash
343  * '/' as the directory separator.  A trailing slash is not needed; it
344  * will be added automatically.
345  */
346 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix);
347 #endif
348
349 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats)
350 {
351         const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */
352
353         FLAC__ASSERT(0 != iterator);
354         FLAC__ASSERT(0 != filename);
355
356         simple_iterator_free_guts_(iterator);
357
358         if(preserve_file_stats)
359                 iterator->has_stats = get_file_stats_(filename, &iterator->stats);
360
361         if(0 == (iterator->filename = strdup(filename))) {
362                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
363                 return false;
364         }
365         if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) {
366                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
367                 return false;
368         }
369
370         return simple_iterator_prime_input_(iterator);
371 }
372
373 FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator)
374 {
375         FLAC__ASSERT(0 != iterator);
376         FLAC__ASSERT(0 != iterator->file);
377
378         return iterator->is_writable;
379 }
380
381 FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator)
382 {
383         FLAC__ASSERT(0 != iterator);
384         FLAC__ASSERT(0 != iterator->file);
385
386         if(iterator->is_last)
387                 return false;
388
389         if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
390                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
391                 return false;
392         }
393
394         iterator->offset[iterator->depth] = ftell(iterator->file);
395
396         return read_metadata_block_header_(iterator);
397 }
398
399 FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator)
400 {
401         long this_offset;
402
403         FLAC__ASSERT(0 != iterator);
404         FLAC__ASSERT(0 != iterator->file);
405
406         if(iterator->offset[iterator->depth] == iterator->first_offset)
407                 return false;
408
409         if(0 != fseek(iterator->file, iterator->first_offset, SEEK_SET)) {
410                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
411                 return false;
412         }
413         this_offset = iterator->first_offset;
414         if(!read_metadata_block_header_(iterator))
415                 return false;
416
417         /* we ignore any error from ftell() and catch it in fseek() */
418         while(ftell(iterator->file) + (long)iterator->length < iterator->offset[iterator->depth]) {
419                 if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
420                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
421                         return false;
422                 }
423                 this_offset = ftell(iterator->file);
424                 if(!read_metadata_block_header_(iterator))
425                         return false;
426         }
427
428         iterator->offset[iterator->depth] = this_offset;
429
430         return true;
431 }
432
433 FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator)
434 {
435         FLAC__ASSERT(0 != iterator);
436         FLAC__ASSERT(0 != iterator->file);
437
438         return iterator->type;
439 }
440
441 FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator)
442 {
443         FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type);
444
445         FLAC__ASSERT(0 != iterator);
446         FLAC__ASSERT(0 != iterator->file);
447
448         if(0 != block) {
449                 block->is_last = iterator->is_last;
450                 block->length = iterator->length;
451
452                 if(!read_metadata_block_data_(iterator, block)) {
453                         FLAC__metadata_object_delete(block);
454                         return 0;
455                 }
456
457                 /* back up to the beginning of the block data to stay consistent */
458                 if(0 != fseek(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
459                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
460                         FLAC__metadata_object_delete(block);
461                         return 0;
462                 }
463         }
464         else
465                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
466
467         return block;
468 }
469
470 FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding)
471 {
472         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
473         FLAC__bool ret;
474
475         FLAC__ASSERT(0 != iterator);
476         FLAC__ASSERT(0 != iterator->file);
477
478         if(!iterator->is_writable) {
479                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
480                 return false;
481         }
482
483         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) {
484                 if(iterator->type != block->type) {
485                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
486                         return false;
487                 }
488         }
489
490         block->is_last = iterator->is_last;
491
492         if(iterator->length == block->length)
493                 return write_metadata_block_stationary_(iterator, block);
494         else if(iterator->length > block->length) {
495                 if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) {
496                         ret =  write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last);
497                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
498                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
499                         return ret;
500                 }
501                 else {
502                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
503                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
504                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
505                         return ret;
506                 }
507         }
508         else /* iterator->length < block->length */ {
509                 unsigned padding_leftover = 0;
510                 FLAC__bool padding_is_last = false;
511                 if(use_padding) {
512                         /* first see if we can even use padding */
513                         if(iterator->is_last) {
514                                 use_padding = false;
515                         }
516                         else {
517                                 const unsigned extra_padding_bytes_required = block->length - iterator->length;
518                                 simple_iterator_push_(iterator);
519                                 if(!FLAC__metadata_simple_iterator_next(iterator)) {
520                                         (void)simple_iterator_pop_(iterator);
521                                         return false;
522                                 }
523                                 if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
524                                         use_padding = false;
525                                 }
526                                 else {
527                                         if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) {
528                                                 padding_leftover = 0;
529                                                 block->is_last = iterator->is_last;
530                                         }
531                                         else if(iterator->length < extra_padding_bytes_required)
532                                                 use_padding = false;
533                                         else {
534                                                 padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required;
535                                                 padding_is_last = iterator->is_last;
536                                                 block->is_last = false;
537                                         }
538                                 }
539                                 if(!simple_iterator_pop_(iterator))
540                                         return false;
541                         }
542                 }
543                 if(use_padding) {
544                         if(padding_leftover == 0) {
545                                 ret = write_metadata_block_stationary_(iterator, block);
546                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
547                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
548                                 return ret;
549                         }
550                         else {
551                                 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
552                                 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
553                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
554                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
555                                 return ret;
556                         }
557                 }
558                 else {
559                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
560                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
561                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
562                         return ret;
563                 }
564         }
565 }
566
567 FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding)
568 {
569         unsigned padding_leftover = 0;
570         FLAC__bool padding_is_last = false;
571
572         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
573         FLAC__bool ret;
574
575         FLAC__ASSERT(0 != iterator);
576         FLAC__ASSERT(0 != iterator->file);
577
578         if(!iterator->is_writable)
579                 return false;
580
581         if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
582                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
583                 return false;
584         }
585
586         block->is_last = iterator->is_last;
587
588         if(use_padding) {
589                 /* first see if we can even use padding */
590                 if(iterator->is_last) {
591                         use_padding = false;
592                 }
593                 else {
594                         simple_iterator_push_(iterator);
595                         if(!FLAC__metadata_simple_iterator_next(iterator)) {
596                                 (void)simple_iterator_pop_(iterator);
597                                 return false;
598                         }
599                         if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
600                                 use_padding = false;
601                         }
602                         else {
603                                 if(iterator->length == block->length) {
604                                         padding_leftover = 0;
605                                         block->is_last = iterator->is_last;
606                                 }
607                                 else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length)
608                                         use_padding = false;
609                                 else {
610                                         padding_leftover = iterator->length - block->length;
611                                         padding_is_last = iterator->is_last;
612                                         block->is_last = false;
613                                 }
614                         }
615                         if(!simple_iterator_pop_(iterator))
616                                 return false;
617                 }
618         }
619         if(use_padding) {
620                 /* move to the next block, which is suitable padding */
621                 if(!FLAC__metadata_simple_iterator_next(iterator))
622                         return false;
623                 if(padding_leftover == 0) {
624                         ret = write_metadata_block_stationary_(iterator, block);
625                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
626                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
627                         return ret;
628                 }
629                 else {
630                         FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
631                         ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
632                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
633                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
634                         return ret;
635                 }
636         }
637         else {
638                 ret = rewrite_whole_file_(iterator, block, /*append=*/true);
639                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
640                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
641                 return ret;
642         }
643 }
644
645 FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding)
646 {
647         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
648         FLAC__bool ret;
649
650         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
651                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
652                 return false;
653         }
654
655         if(use_padding) {
656                 FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
657                 if(0 == padding) {
658                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
659                         return false;
660                 }
661                 padding->length = iterator->length;
662                 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) {
663                         FLAC__metadata_object_delete(padding);
664                         return false;
665                 }
666                 FLAC__metadata_object_delete(padding);
667                 if(!FLAC__metadata_simple_iterator_prev(iterator))
668                         return false;
669                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
670                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
671                 return true;
672         }
673         else {
674                 ret = rewrite_whole_file_(iterator, 0, /*append=*/false);
675                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
676                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
677                 return ret;
678         }
679 }
680
681
682
683 /****************************************************************************
684  *
685  * Level 2 implementation
686  *
687  ***************************************************************************/
688
689
690 typedef struct FLAC__Metadata_Node {
691         FLAC__StreamMetadata *data;
692         struct FLAC__Metadata_Node *prev, *next;
693 } FLAC__Metadata_Node;
694
695 struct FLAC__Metadata_Chain {
696         char *filename;
697         FLAC__Metadata_Node *head;
698         FLAC__Metadata_Node *tail;
699         unsigned nodes;
700         FLAC__Metadata_ChainStatus status;
701         long first_offset, last_offset; /*@@@ 2G limit */
702         /*
703          * This is the length of the chain initially read from the FLAC file.
704          * it is used to compare against the current_length to decide whether
705          * or not the whole file has to be rewritten.
706          */
707         unsigned initial_length; /*@@@ 4G limit */
708         unsigned current_length; /*@@@ 4G limit */
709 };
710
711 struct FLAC__Metadata_Iterator {
712         FLAC__Metadata_Chain *chain;
713         FLAC__Metadata_Node *current;
714 };
715
716 const char * const FLAC__Metadata_ChainStatusString[] = {
717         "FLAC__METADATA_CHAIN_STATUS_OK",
718         "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT",
719         "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE",
720         "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE",
721         "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE",
722         "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA",
723         "FLAC__METADATA_CHAIN_STATUS_READ_ERROR",
724         "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR",
725         "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR",
726         "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
727         "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
728         "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
729         "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR"
730 };
731
732
733 static FLAC__Metadata_Node *node_new_()
734 {
735         FLAC__Metadata_Node *node = (FLAC__Metadata_Node*)malloc(sizeof(FLAC__Metadata_Node));
736         if(0 != node)
737                 memset(node, 0, sizeof(FLAC__Metadata_Node));
738         return node;
739 }
740
741 static void node_delete_(FLAC__Metadata_Node *node)
742 {
743         FLAC__ASSERT(0 != node);
744         if(0 != node->data)
745                 FLAC__metadata_object_delete(node->data);
746         free(node);
747 }
748
749 static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
750 {
751         FLAC__ASSERT(0 != chain);
752         FLAC__ASSERT(0 != node);
753         FLAC__ASSERT(0 != node->data);
754
755         node->next = node->prev = 0;
756         node->data->is_last = true;
757         if(0 != chain->tail)
758                 chain->tail->data->is_last = false;
759
760         if(0 == chain->head)
761                 chain->head = node;
762         else {
763                 FLAC__ASSERT(0 != chain->tail);
764                 chain->tail->next = node;
765                 node->prev = chain->tail;
766         }
767         chain->tail = node;
768         chain->nodes++;
769         chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
770 }
771
772 static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
773 {
774         FLAC__ASSERT(0 != chain);
775         FLAC__ASSERT(0 != node);
776
777         if(node == chain->head)
778                 chain->head = node->next;
779         else
780                 node->prev->next = node->next;
781
782         if(node == chain->tail)
783                 chain->tail = node->prev;
784         else
785                 node->next->prev = node->prev;
786
787         if(0 != chain->tail)
788                 chain->tail->data->is_last = true;
789
790         chain->nodes--;
791         chain->current_length -= (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
792 }
793
794 static void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
795 {
796         chain_remove_node_(chain, node);
797         node_delete_(node);
798 }
799
800 static void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
801 {
802         FLAC__ASSERT(0 != node);
803         FLAC__ASSERT(0 != node->data);
804         FLAC__ASSERT(0 != iterator);
805         FLAC__ASSERT(0 != iterator->current);
806         FLAC__ASSERT(0 != iterator->chain);
807         FLAC__ASSERT(0 != iterator->chain->head);
808         FLAC__ASSERT(0 != iterator->chain->tail);
809
810         node->data->is_last = false;
811
812         node->prev = iterator->current->prev;
813         node->next = iterator->current;
814
815         if(0 == node->prev)
816                 iterator->chain->head = node;
817         else
818                 node->prev->next = node;
819
820         iterator->current->prev = node;
821
822         iterator->chain->nodes++;
823         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
824 }
825
826 static void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
827 {
828         FLAC__ASSERT(0 != node);
829         FLAC__ASSERT(0 != node->data);
830         FLAC__ASSERT(0 != iterator);
831         FLAC__ASSERT(0 != iterator->current);
832         FLAC__ASSERT(0 != iterator->chain);
833         FLAC__ASSERT(0 != iterator->chain->head);
834         FLAC__ASSERT(0 != iterator->chain->tail);
835
836         iterator->current->data->is_last = false;
837
838         node->prev = iterator->current;
839         node->next = iterator->current->next;
840
841         if(0 == node->next)
842                 iterator->chain->tail = node;
843         else
844                 node->next->prev = node;
845
846         node->prev->next = node;
847
848         iterator->chain->tail->data->is_last = true;
849
850         iterator->chain->nodes++;
851         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
852 }
853
854 /* return true iff node and node->next are both padding */
855 static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
856 {
857         if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) {
858                 const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length;
859                 node->data->length += growth;
860                 chain->current_length += growth;
861
862                 chain_delete_node_(chain, node->next);
863                 return true;
864         }
865         else
866                 return false;
867 }
868
869 FLAC__Metadata_Chain *FLAC__metadata_chain_new()
870 {
871         FLAC__Metadata_Chain *chain = malloc(sizeof(FLAC__Metadata_Chain));
872
873         if(0 != chain) {
874                 chain->filename = 0;
875                 chain->head = chain->tail = 0;
876                 chain->nodes = 0;
877                 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
878                 chain->initial_length = chain->current_length = 0;
879         }
880
881         return chain;
882 }
883
884 void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain)
885 {
886         FLAC__Metadata_Node *node, *next;
887
888         FLAC__ASSERT(0 != chain);
889
890         for(node = chain->head; node; ) {
891                 next = node->next;
892                 node_delete_(node);
893                 node = next;
894         }
895
896         if(0 != chain->filename)
897                 free(chain->filename);
898
899         free(chain);
900 }
901
902 FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain)
903 {
904         FLAC__Metadata_ChainStatus status;
905
906         FLAC__ASSERT(0 != chain);
907
908         status = chain->status;
909         chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
910         return status;
911 }
912
913 FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
914 {
915         FLAC__Metadata_SimpleIterator *iterator;
916         FLAC__Metadata_Node *node;
917
918         FLAC__ASSERT(0 != chain);
919         FLAC__ASSERT(0 != filename);
920
921         if(0 == (chain->filename = strdup(filename))) {
922                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
923                 return false;
924         }
925
926         if(0 == (iterator = FLAC__metadata_simple_iterator_new())) {
927                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
928                 return false;
929         }
930
931         if(!FLAC__metadata_simple_iterator_init(iterator, filename, /*preserve_file_stats=*/false)) {
932                 chain->status = get_equivalent_status_(iterator->status);
933                 return false;
934         }
935
936         chain->first_offset = iterator->offset[iterator->depth];
937
938         do {
939                 node = node_new_();
940                 if(0 == node) {
941                         chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
942                         return false;
943                 }
944                 node->data = FLAC__metadata_simple_iterator_get_block(iterator);
945                 if(0 == node->data) {
946                         node_delete_(node);
947                         chain->status = get_equivalent_status_(iterator->status);
948                         return false;
949                 }
950                 chain_append_node_(chain, node);
951         } while(FLAC__metadata_simple_iterator_next(iterator));
952
953         if(!iterator->is_last || iterator->status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) {
954                 chain->status = get_equivalent_status_(iterator->status);
955                 return false;
956         }
957
958         chain->last_offset = ftell(iterator->file) + iterator->length;
959         FLAC__metadata_simple_iterator_delete(iterator);
960
961         chain->initial_length = chain->current_length;
962         return true;
963 }
964
965 FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
966 {
967         struct stat stats;
968         const char *tempfile_path_prefix = 0;
969
970         if(use_padding) {
971                 if(chain->current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
972                         const unsigned delta = chain->initial_length - chain->current_length;
973                         chain->tail->data->length += delta;
974                         chain->current_length += delta;
975                         FLAC__ASSERT(chain->current_length == chain->initial_length);
976                 }
977                 else if(chain->current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
978                         FLAC__StreamMetadata *padding;
979                         FLAC__Metadata_Node *node;
980                         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
981                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
982                                 return false;
983                         }
984                         padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + chain->current_length);
985                         if(0 == (node = node_new_())) {
986                                 FLAC__metadata_object_delete(padding);
987                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
988                                 return false;
989                         }
990                         node->data = padding;
991                         chain_append_node_(chain, node);
992                         FLAC__ASSERT(chain->current_length == chain->initial_length);
993                 }
994                 else if(chain->current_length > chain->initial_length) {
995                         const unsigned delta = chain->current_length - chain->initial_length;
996                         if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
997                                 if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
998                                         chain_delete_node_(chain, chain->tail);
999                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
1000                                 }
1001                                 else if(chain->tail->data->length >= delta) {
1002                                         chain->tail->data->length -= delta;
1003                                         chain->current_length -= delta;
1004                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
1005                                 }
1006                         }
1007                 }
1008         }
1009
1010         if(preserve_file_stats)
1011                 get_file_stats_(chain->filename, &stats);
1012
1013         if(chain->current_length == chain->initial_length) {
1014                 if(!chain_rewrite_chain_(chain))
1015                         return false;
1016         }
1017         else {
1018                 if(!chain_rewrite_file_(chain, tempfile_path_prefix))
1019                         return false;
1020         }
1021
1022         if(preserve_file_stats)
1023                 set_file_stats_(chain->filename, &stats);
1024
1025         /* recompute lengths and offsets if necessary */
1026         if(chain->initial_length != chain->current_length) {
1027                 const FLAC__Metadata_Node *node;
1028                 chain->initial_length = chain->current_length;
1029                 chain->last_offset = chain->first_offset;
1030                 for(node = chain->head; node; node = node->next)
1031                         chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1032         }
1033
1034         return true;
1035 }
1036
1037 void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain)
1038 {
1039         FLAC__Metadata_Node *node;
1040
1041         FLAC__ASSERT(0 != chain);
1042
1043         for(node = chain->head; node; ) {
1044                 if(!chain_merge_adjacent_padding_(chain, node))
1045                         node = node->next;
1046         }
1047 }
1048
1049 void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain)
1050 {
1051         FLAC__Metadata_Node *node, *save;
1052         unsigned i;
1053
1054         FLAC__ASSERT(0 != chain);
1055
1056         /*
1057          * Don't try and be too smart... this simple algo is good enough for
1058          * the small number of nodes that we deal with.
1059          */
1060         for(i = 0, node = chain->head; i < chain->nodes; i++) {
1061                 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1062                         save = node->next;
1063                         chain_remove_node_(chain, node);
1064                         chain_append_node_(chain, node);
1065                         node = save;
1066                 }
1067                 else {
1068                         node = node->next;
1069                 }
1070         }
1071
1072         FLAC__metadata_chain_merge_padding(chain);
1073 }
1074
1075
1076 FLAC__Metadata_Iterator *FLAC__metadata_iterator_new()
1077 {
1078         FLAC__Metadata_Iterator *iterator = malloc(sizeof(FLAC__Metadata_Iterator));
1079
1080         if(0 != iterator) {
1081                 iterator->current = 0;
1082                 iterator->chain = 0;
1083         }
1084
1085         return iterator;
1086 }
1087
1088 void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator)
1089 {
1090         FLAC__ASSERT(0 != iterator);
1091
1092         free(iterator);
1093 }
1094
1095 /*
1096  * Initialize the iterator to point to the first metadata block in the
1097  * given chain.
1098  */
1099 void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain)
1100 {
1101         FLAC__ASSERT(0 != iterator);
1102         FLAC__ASSERT(0 != chain);
1103         FLAC__ASSERT(0 != chain->head);
1104
1105         iterator->chain = chain;
1106         iterator->current = chain->head;
1107 }
1108
1109 FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator)
1110 {
1111         FLAC__ASSERT(0 != iterator);
1112
1113         if(0 == iterator->current || 0 == iterator->current->next)
1114                 return false;
1115
1116         iterator->current = iterator->current->next;
1117         return true;
1118 }
1119
1120 FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator)
1121 {
1122         FLAC__ASSERT(0 != iterator);
1123
1124         if(0 == iterator->current || 0 == iterator->current->prev)
1125                 return false;
1126
1127         iterator->current = iterator->current->prev;
1128         return true;
1129 }
1130
1131 FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator)
1132 {
1133         FLAC__ASSERT(0 != iterator);
1134         FLAC__ASSERT(0 != iterator->current);
1135         FLAC__ASSERT(0 != iterator->current->data);
1136
1137         return iterator->current->data->type;
1138 }
1139
1140 FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator)
1141 {
1142         FLAC__ASSERT(0 != iterator);
1143         FLAC__ASSERT(0 != iterator->current);
1144
1145         return iterator->current->data;
1146 }
1147
1148 FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1149 {
1150         return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
1151 }
1152
1153 FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding)
1154 {
1155         FLAC__Metadata_Node *save;
1156
1157         FLAC__ASSERT(0 != iterator);
1158         FLAC__ASSERT(0 != iterator->current);
1159
1160         if(0 == iterator->current->prev) {
1161                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1162                 return false;
1163         }
1164
1165         save = iterator->current->prev;
1166
1167         if(replace_with_padding) {
1168                 FLAC__metadata_object_delete_data(iterator->current->data);
1169                 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
1170         }
1171         else {
1172                 chain_delete_node_(iterator->chain, iterator->current);
1173         }
1174
1175         iterator->current = save;
1176         return true;
1177 }
1178
1179 FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1180 {
1181         FLAC__Metadata_Node *node;
1182
1183         FLAC__ASSERT(0 != iterator);
1184         FLAC__ASSERT(0 != iterator->current);
1185
1186         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1187                 return false;
1188
1189         if(0 == iterator->current->prev) {
1190                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1191                 return false;
1192         }
1193
1194         if(0 == (node = node_new_()))
1195                 return false;
1196
1197         node->data = block;
1198         iterator_insert_node_(iterator, node);
1199         iterator->current = node;
1200         return true;
1201 }
1202
1203 FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1204 {
1205         FLAC__Metadata_Node *node;
1206
1207         FLAC__ASSERT(0 != iterator);
1208         FLAC__ASSERT(0 != iterator->current);
1209
1210         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1211                 return false;
1212
1213         if(0 == (node = node_new_()))
1214                 return false;
1215
1216         node->data = block;
1217         iterator_insert_node_after_(iterator, node);
1218         iterator->current = node;
1219         return true;
1220 }
1221
1222
1223 /****************************************************************************
1224  *
1225  * Local function definitions
1226  *
1227  ***************************************************************************/
1228
1229 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1230 {
1231         unsigned i;
1232
1233         b += bytes;
1234
1235         for(i = 0; i < bytes; i++) {
1236                 *(--b) = (FLAC__byte)(val & 0xff);
1237                 val >>= 8;
1238         }
1239 }
1240
1241 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1242 {
1243         unsigned i;
1244
1245         for(i = 0; i < bytes; i++) {
1246                 *(b++) = (FLAC__byte)(val & 0xff);
1247                 val >>= 8;
1248         }
1249 }
1250
1251 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes)
1252 {
1253         unsigned i;
1254
1255         b += bytes;
1256
1257         for(i = 0; i < bytes; i++) {
1258                 *(--b) = (FLAC__byte)(val & 0xff);
1259                 val >>= 8;
1260         }
1261 }
1262
1263 FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes)
1264 {
1265         FLAC__uint32 ret = 0;
1266         unsigned i;
1267
1268         for(i = 0; i < bytes; i++)
1269                 ret = (ret << 8) | (FLAC__uint32)(*b++);
1270
1271         return ret;
1272 }
1273
1274 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes)
1275 {
1276         FLAC__uint32 ret = 0;
1277         unsigned i;
1278
1279         b += bytes;
1280
1281         for(i = 0; i < bytes; i++)
1282                 ret = (ret << 8) | (FLAC__uint32)(*--b);
1283
1284         return ret;
1285 }
1286
1287 FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes)
1288 {
1289         FLAC__uint64 ret = 0;
1290         unsigned i;
1291
1292         for(i = 0; i < bytes; i++)
1293                 ret = (ret << 8) | (FLAC__uint64)(*b++);
1294
1295         return ret;
1296 }
1297
1298 FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator)
1299 {
1300         FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
1301
1302         FLAC__ASSERT(0 != iterator);
1303         FLAC__ASSERT(0 != iterator->file);
1304
1305         if(fread(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, iterator->file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1306                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1307                 return false;
1308         }
1309
1310         iterator->is_last = raw_header[0] & 0x80? true : false;
1311         iterator->type = (FLAC__MetadataType)(raw_header[0] & 0x7f);
1312         iterator->length = unpack_uint32_(raw_header + 1, 3);
1313
1314         /* do some checking */
1315         if(iterator->type > FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1316                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
1317                 return false;
1318         }
1319
1320         return true;
1321 }
1322
1323 FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block)
1324 {
1325         FLAC__ASSERT(0 != iterator);
1326         FLAC__ASSERT(0 != iterator->file);
1327
1328         switch(block->type) {
1329                 case FLAC__METADATA_TYPE_STREAMINFO:
1330                         iterator->status = read_metadata_block_data_streaminfo_(iterator->file, &block->data.stream_info);
1331                         break;
1332                 case FLAC__METADATA_TYPE_PADDING:
1333                         iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length);
1334                         break;
1335                 case FLAC__METADATA_TYPE_APPLICATION:
1336                         iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length);
1337                         break;
1338                 case FLAC__METADATA_TYPE_SEEKTABLE:
1339                         iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length);
1340                         break;
1341                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1342                         iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment);
1343                         break;
1344                 default:
1345                         FLAC__ASSERT(0);
1346                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1347         }
1348
1349         return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1350 }
1351
1352 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block)
1353 {
1354         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
1355
1356         FLAC__ASSERT(0 != file);
1357
1358         if(fread(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1359                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1360
1361         b = buffer;
1362
1363         /* @@@ we are using hardcoded numbers for simplicity but we should
1364          * probably eventually write a bit-level unpacker and use the
1365          * _STREAMINFO_ constants.
1366          */
1367         block->min_blocksize = unpack_uint32_(b, 2); b += 2;
1368         block->max_blocksize = unpack_uint32_(b, 2); b += 2;
1369         block->min_framesize = unpack_uint32_(b, 3); b += 3;
1370         block->max_framesize = unpack_uint32_(b, 3); b += 3;
1371         block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
1372         block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
1373         block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 1) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
1374         block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
1375         memcpy(block->md5sum, b+8, 16);
1376
1377         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1378 }
1379
1380
1381 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetadata_Padding *block, unsigned block_length)
1382 {
1383         FLAC__ASSERT(0 != file);
1384
1385         (void)block; /* nothing to do; we don't care about reading the padding bytes */
1386
1387         if(0 != fseek(file, block_length, SEEK_CUR))
1388                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1389
1390         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1391 }
1392
1393 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetadata_Application *block, unsigned block_length)
1394 {
1395         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1396
1397         FLAC__ASSERT(0 != file);
1398
1399         if(fread(block->id, 1, id_bytes, file) != id_bytes)
1400                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1401
1402         block_length -= id_bytes;
1403
1404         if(block_length == 0) {
1405                 block->data = 0;
1406         }
1407         else {
1408                 if(0 == (block->data = malloc(block_length)))
1409                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1410
1411                 if(fread(block->data, 1, block_length, file) != block_length)
1412                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1413         }
1414
1415         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1416 }
1417
1418 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetadata_SeekTable *block, unsigned block_length)
1419 {
1420         unsigned i;
1421         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1422
1423         FLAC__ASSERT(0 != file);
1424         FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0);
1425
1426         block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1427
1428         if(block->num_points == 0)
1429                 block->points = 0;
1430         else if(0 == (block->points = malloc(block->num_points * sizeof(FLAC__StreamMetadata_SeekPoint))))
1431                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1432
1433         for(i = 0; i < block->num_points; i++) {
1434                 if(fread(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1435                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1436                 /*@@@ some MAGIC NUMBERs here */
1437                 block->points[i].sample_number = unpack_uint64_(buffer, 8);
1438                 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
1439                 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
1440         }
1441
1442         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1443 }
1444
1445 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetadata_VorbisComment_Entry *entry)
1446 {
1447         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1448         FLAC__byte buffer[4]; /* magic number is asserted below */
1449
1450         FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
1451         FLAC__ASSERT(0 != file);
1452
1453         if(fread(buffer, 1, entry_length_len, file) != entry_length_len)
1454                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1455         entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
1456
1457         if(entry->length == 0) {
1458                 entry->entry = 0;
1459         }
1460         else {
1461                 if(0 == (entry->entry = malloc(entry->length)))
1462                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1463
1464                 if(fread(entry->entry, 1, entry->length, file) != entry->length)
1465                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1466         }
1467
1468         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1469 }
1470
1471 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block)
1472 {
1473         unsigned i;
1474         FLAC__Metadata_SimpleIteratorStatus status;
1475         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1476         FLAC__byte buffer[4]; /* magic number is asserted below */
1477
1478         FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
1479         FLAC__ASSERT(0 != file);
1480
1481         if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, &(block->vendor_string))))
1482                 return status;
1483
1484         if(fread(buffer, 1, num_comments_len, file) != num_comments_len)
1485                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1486         block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
1487
1488         if(block->num_comments == 0) {
1489                 block->comments = 0;
1490         }
1491         else if(0 == (block->comments = malloc(block->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry))))
1492                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1493
1494         for(i = 0; i < block->num_comments; i++) {
1495                 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, block->comments + i)))
1496                         return status;
1497         }
1498
1499         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1500 }
1501
1502 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
1503 {
1504         FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
1505
1506         FLAC__ASSERT(0 != file);
1507         FLAC__ASSERT(0 != status);
1508         FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
1509
1510         buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type;
1511         pack_uint32_(block->length, buffer + 1, 3);
1512
1513         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1514                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1515                 return false;
1516         }
1517
1518         return true;
1519 }
1520
1521 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
1522 {
1523         FLAC__ASSERT(0 != file);
1524         FLAC__ASSERT(0 != status);
1525
1526         switch(block->type) {
1527                 case FLAC__METADATA_TYPE_STREAMINFO:
1528                         *status = write_metadata_block_data_streaminfo_(file, &block->data.stream_info);
1529                         break;
1530                 case FLAC__METADATA_TYPE_PADDING:
1531                         *status = write_metadata_block_data_padding_(file, &block->data.padding, block->length);
1532                         break;
1533                 case FLAC__METADATA_TYPE_APPLICATION:
1534                         *status = write_metadata_block_data_application_(file, &block->data.application, block->length);
1535                         break;
1536                 case FLAC__METADATA_TYPE_SEEKTABLE:
1537                         *status = write_metadata_block_data_seektable_(file, &block->data.seek_table);
1538                         break;
1539                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1540                         *status = write_metadata_block_data_vorbis_comment_(file, &block->data.vorbis_comment);
1541                         break;
1542                 default:
1543                         FLAC__ASSERT(0);
1544                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1545         }
1546         return (*status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1547 }
1548
1549 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetadata_StreamInfo *block)
1550 {
1551         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
1552         const unsigned channels1 = block->channels - 1;
1553         const unsigned bps1 = block->bits_per_sample - 1;
1554
1555         FLAC__ASSERT(0 != file);
1556
1557         /* @@@ we are using hardcoded numbers for simplicity but we should
1558          * probably eventually write a bit-level packer and use the
1559          * _STREAMINFO_ constants.
1560          */
1561         pack_uint32_(block->min_blocksize, buffer, 2);
1562         pack_uint32_(block->max_blocksize, buffer+2, 2);
1563         pack_uint32_(block->min_framesize, buffer+4, 3);
1564         pack_uint32_(block->max_framesize, buffer+7, 3);
1565         buffer[10] = (block->sample_rate >> 12) & 0xff;
1566         buffer[11] = (block->sample_rate >> 4) & 0xff;
1567         buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4);
1568         buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f));
1569         pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4);
1570         memcpy(buffer+18, block->md5sum, 16);
1571
1572         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1573                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1574
1575         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1576 }
1577
1578 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetadata_Padding *block, unsigned block_length)
1579 {
1580         unsigned i, n = block_length;
1581         FLAC__byte buffer[1024];
1582
1583         FLAC__ASSERT(0 != file);
1584
1585         (void)block;
1586
1587         memset(buffer, 0, 1024);
1588
1589         for(i = 0; i < n/1024; i++)
1590                 if(fwrite(buffer, 1, 1024, file) != 1024)
1591                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1592
1593         n %= 1024;
1594         
1595         if(fwrite(buffer, 1, n, file) != n)
1596                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1597
1598         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1599 }
1600
1601 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetadata_Application *block, unsigned block_length)
1602 {
1603         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1604
1605         FLAC__ASSERT(0 != file);
1606
1607         if(fwrite(block->id, 1, id_bytes, file) != id_bytes)
1608                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1609
1610         block_length -= id_bytes;
1611
1612         if(fwrite(block->data, 1, block_length, file) != block_length)
1613                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1614
1615         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1616 }
1617
1618 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetadata_SeekTable *block)
1619 {
1620         unsigned i;
1621         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1622
1623         FLAC__ASSERT(0 != file);
1624
1625         for(i = 0; i < block->num_points; i++) {
1626                 /*@@@ some MAGIC NUMBERs here */
1627                 pack_uint64_(block->points[i].sample_number, buffer, 8);
1628                 pack_uint64_(block->points[i].stream_offset, buffer+8, 8);
1629                 pack_uint32_(block->points[i].frame_samples, buffer+16, 2);
1630                 if(fwrite(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1631                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1632         }
1633
1634         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1635 }
1636
1637 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetadata_VorbisComment *block)
1638 {
1639         unsigned i;
1640         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1641         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1642         FLAC__byte buffer[4]; /* magic number is asserted below */
1643
1644         FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == 4);
1645         FLAC__ASSERT(0 != file);
1646
1647         pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
1648         if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
1649                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1650         if(fwrite(block->vendor_string.entry, 1, block->vendor_string.length, file) != block->vendor_string.length)
1651                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1652
1653         pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len);
1654         if(fwrite(buffer, 1, num_comments_len, file) != num_comments_len)
1655                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1656
1657         for(i = 0; i < block->num_comments; i++) {
1658                 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len);
1659                 if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
1660                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1661                 if(fwrite(block->comments[i].entry, 1, block->comments[i].length, file) != block->comments[i].length)
1662                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1663         }
1664
1665         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1666 }
1667
1668 FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block)
1669 {
1670         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1671                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1672                 return false;
1673         }
1674
1675         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
1676                 return false;
1677
1678         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
1679                 return false;
1680
1681         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1682                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1683                 return false;
1684         }
1685
1686         return read_metadata_block_header_(iterator);
1687 }
1688
1689 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last)
1690 {
1691         FLAC__StreamMetadata *padding;
1692
1693         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1694                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1695                 return false;
1696         }
1697
1698         block->is_last = false;
1699
1700         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
1701                 return false;
1702
1703         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
1704                 return false;
1705
1706         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1707                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1708
1709         padding->is_last = padding_is_last;
1710         padding->length = padding_length;
1711
1712         if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) {
1713                 FLAC__metadata_object_delete(padding);
1714                 return false;
1715         }
1716
1717         if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) {
1718                 FLAC__metadata_object_delete(padding);
1719                 return false;
1720         }
1721
1722         FLAC__metadata_object_delete(padding);
1723
1724         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1725                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1726                 return false;
1727         }
1728
1729         return read_metadata_block_header_(iterator);
1730 }
1731
1732 FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append)
1733 {
1734         FILE *tempfile;
1735         char *tempfilename;
1736         int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
1737         long fixup_is_last_flag_offset = -1;
1738
1739         FLAC__ASSERT(0 != block || append == false);
1740
1741         if(iterator->is_last) {
1742                 if(append) {
1743                         fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */
1744                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
1745                 }
1746                 else if(0 == block) {
1747                         simple_iterator_push_(iterator);
1748                         if(!FLAC__metadata_simple_iterator_prev(iterator)) {
1749                                 (void)simple_iterator_pop_(iterator);
1750                                 return false;
1751                         }
1752                         fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */
1753                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
1754                         if(!simple_iterator_pop_(iterator))
1755                                 return false;
1756                 }
1757         }
1758
1759         if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append))
1760                 return false;
1761
1762         if(0 != block) {
1763                 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) {
1764                         cleanup_tempfile_(&tempfile, &tempfilename);
1765                         return false;
1766                 }
1767
1768                 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) {
1769                         cleanup_tempfile_(&tempfile, &tempfilename);
1770                         return false;
1771                 }
1772         }
1773
1774         if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0))
1775                 return false;
1776
1777         if(append)
1778                 return FLAC__metadata_simple_iterator_next(iterator);
1779
1780         return true;
1781 }
1782
1783 FLAC__bool chain_rewrite_chain_(FLAC__Metadata_Chain *chain)
1784 {
1785         FILE *f;
1786         FLAC__Metadata_Node *node;
1787         FLAC__Metadata_SimpleIteratorStatus status;
1788
1789         FLAC__ASSERT(0 != chain);
1790         FLAC__ASSERT(0 != chain->filename);
1791         FLAC__ASSERT(0 != chain->head);
1792
1793         if(0 == (f = fopen(chain->filename, "r+b"))) {
1794                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1795                 return false;
1796         }
1797         if(0 != fseek(f, chain->first_offset, SEEK_SET)) {
1798                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1799                 return false;
1800         }
1801
1802         for(node = chain->head; node; node = node->next) {
1803                 if(!write_metadata_block_header_(f, &status, node->data)) {
1804                         chain->status = get_equivalent_status_(status);
1805                         return false;
1806                 }
1807                 if(!write_metadata_block_data_(f, &status, node->data)) {
1808                         chain->status = get_equivalent_status_(status);
1809                         return false;
1810                 }
1811         }
1812
1813         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
1814
1815         (void)fclose(f);
1816
1817         return true;
1818 }
1819
1820 FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix)
1821 {
1822         FILE *f, *tempfile;
1823         char *tempfilename;
1824         FLAC__Metadata_SimpleIteratorStatus status;
1825         const FLAC__Metadata_Node *node;
1826
1827         FLAC__ASSERT(0 != chain);
1828         FLAC__ASSERT(0 != chain->filename);
1829         FLAC__ASSERT(0 != chain->head);
1830
1831         /* copy the file prefix (data up to first metadata block */
1832         if(0 == (f = fopen(chain->filename, "rb"))) {
1833                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1834                 return false;
1835         }
1836         if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) {
1837                 chain->status = get_equivalent_status_(status);
1838                 cleanup_tempfile_(&tempfile, &tempfilename);
1839                 return false;
1840         }
1841         if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) {
1842                 chain->status = get_equivalent_status_(status);
1843                 cleanup_tempfile_(&tempfile, &tempfilename);
1844                 return false;
1845         }
1846
1847         /* write the metadata */
1848         for(node = chain->head; node; node = node->next) {
1849                 if(!write_metadata_block_header_(tempfile, &status, node->data)) {
1850                         chain->status = get_equivalent_status_(status);
1851                         return false;
1852                 }
1853                 if(!write_metadata_block_data_(tempfile, &status, node->data)) {
1854                         chain->status = get_equivalent_status_(status);
1855                         return false;
1856                 }
1857         }
1858         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
1859
1860         /* copy the file postfix (everything after the metadata) */
1861         if(0 != fseek(f, chain->last_offset, SEEK_SET)) {
1862                 cleanup_tempfile_(&tempfile, &tempfilename);
1863                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1864                 return false;
1865         }
1866         if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) {
1867                 cleanup_tempfile_(&tempfile, &tempfilename);
1868                 chain->status = get_equivalent_status_(status);
1869                 return false;
1870         }
1871
1872         /* move the tempfile on top of the original */
1873         (void)fclose(f);
1874         if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
1875                 return false;
1876
1877         return true;
1878 }
1879
1880 void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator)
1881 {
1882         FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH);
1883         iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth];
1884         iterator->depth++;
1885 }
1886
1887 FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator)
1888 {
1889         FLAC__ASSERT(iterator->depth > 0);
1890         iterator->depth--;
1891         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1892                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1893                 return false;
1894         }
1895
1896         return read_metadata_block_header_(iterator);
1897 }
1898
1899 unsigned seek_to_first_metadata_block_(FILE *f)
1900 {
1901         FLAC__byte buffer[4];
1902         size_t n;
1903         unsigned i;
1904
1905         FLAC__ASSERT(0 != f);
1906         FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
1907
1908         /* skip any id3v2 tag */
1909         errno = 0;
1910         n = fread(buffer, 1, 4, f);
1911         if(errno)
1912                 return 1;
1913         else if(n != 4)
1914                 return 2;
1915         else if(0 == memcmp(buffer, "ID3", 3)) {
1916                 unsigned tag_length = 0;
1917
1918                 /* skip to the tag length */
1919                 if(fseek(f, 2, SEEK_CUR) < 0)
1920                         return 1;
1921
1922                 /* read the length */
1923                 for(i = 0; i < 4; i++) {
1924                         if(fread(buffer, 1, 1, f) < 1 || buffer[0] & 0x80)
1925                                 return 1;
1926                         tag_length <<= 7;
1927                         tag_length |= (buffer[0] & 0x7f);
1928                 }
1929
1930                 /* skip the rest of the tag */
1931                 if(fseek(f, tag_length, SEEK_CUR) < 0)
1932                         return 1;
1933
1934                 /* read the stream sync code */
1935                 errno = 0;
1936                 n = fread(buffer, 1, 4, f);
1937                 if(errno)
1938                         return 1;
1939                 else if(n != 4)
1940                         return 2;
1941         }
1942
1943         /* check for the fLaC signature */
1944         if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH))
1945                 return 0;
1946         else
1947                 return 2;
1948 }
1949
1950 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
1951 {
1952         const long offset_end = append? iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length : iterator->offset[iterator->depth];
1953
1954         if(0 != fseek(iterator->file, 0, SEEK_SET)) {
1955                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1956                 return false;
1957         }
1958         if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) {
1959                 cleanup_tempfile_(tempfile, tempfilename);
1960                 return false;
1961         }
1962         if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) {
1963                 cleanup_tempfile_(tempfile, tempfilename);
1964                 return false;
1965         }
1966
1967         return true;
1968 }
1969
1970 FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, long fixup_is_last_flag_offset, FLAC__bool backup)
1971 {
1972         long save_offset = iterator->offset[iterator->depth]; /*@@@ 2G limit */
1973         FLAC__ASSERT(0 != *tempfile);
1974
1975         if(0 != fseek(iterator->file, save_offset + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length, SEEK_SET)) {
1976                 cleanup_tempfile_(tempfile, tempfilename);
1977                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1978                 return false;
1979         }
1980         if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) {
1981                 cleanup_tempfile_(tempfile, tempfilename);
1982                 return false;
1983         }
1984
1985         if(fixup_is_last_code != 0) {
1986                 /*
1987                  * if code == 1, it means a block was appended to the end so
1988                  *   we have to clear the is_last flag of the previous block
1989                  * if code == -1, it means the last block was deleted so
1990                  *   we have to set the is_last flag of the previous block
1991                  */
1992                 /*@@@ MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
1993                 FLAC__byte x;
1994                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
1995                         cleanup_tempfile_(tempfile, tempfilename);
1996                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1997                         return false;
1998                 }
1999                 if(fread(&x, 1, 1, *tempfile) != 1) {
2000                         cleanup_tempfile_(tempfile, tempfilename);
2001                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2002                         return false;
2003                 }
2004                 if(fixup_is_last_code > 0) {
2005                         FLAC__ASSERT(x & 0x80);
2006                         x &= 0x7f;
2007                 }
2008                 else {
2009                         FLAC__ASSERT(!(x & 0x80));
2010                         x |= 0x80;
2011                 }
2012                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2013                         cleanup_tempfile_(tempfile, tempfilename);
2014                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2015                         return false;
2016                 }
2017                 if(fwrite(&x, 1, 1, *tempfile) != 1) {
2018                         cleanup_tempfile_(tempfile, tempfilename);
2019                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2020                         return false;
2021                 }
2022         }
2023
2024         (void)fclose(iterator->file);
2025
2026         if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status))
2027                 return false;
2028
2029         if(iterator->has_stats)
2030                 set_file_stats_(iterator->filename, &iterator->stats);
2031
2032         if(!simple_iterator_prime_input_(iterator))
2033                 return false;
2034         if(backup) {
2035                 while(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length < save_offset)
2036                         if(!FLAC__metadata_simple_iterator_next(iterator))
2037                                 return false;
2038                 return true;
2039         }
2040         else {
2041                 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */
2042                 FLAC__ASSERT(iterator->depth == 0);
2043                 iterator->offset[0] = save_offset;
2044                 iterator->depth++;
2045                 return simple_iterator_pop_(iterator);
2046         }
2047 }
2048
2049 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status)
2050 {
2051         FLAC__byte buffer[8192];
2052         unsigned n;
2053
2054         while(bytes > 0) {
2055                 n = min(sizeof(buffer), bytes);
2056                 if(fread(buffer, 1, n, file) != n) {
2057                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2058                         return false;
2059                 }
2060                 if(fwrite(buffer, 1, n, tempfile) != n) {
2061                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2062                         return false;
2063                 }
2064                 bytes -= n;
2065         }
2066
2067         return true;
2068 }
2069
2070 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status)
2071 {
2072         FLAC__byte buffer[8192];
2073         size_t n;
2074
2075         while(!feof(file)) {
2076                 n = fread(buffer, 1, sizeof(buffer), file);
2077                 if(n == 0 && !feof(file)) {
2078                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2079                         return false;
2080                 }
2081                 if(n > 0 && fwrite(buffer, 1, n, tempfile) != n) {
2082                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2083                         return false;
2084                 }
2085         }
2086
2087         return true;
2088 }
2089
2090 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
2091 {
2092         static const char *tempfile_suffix = ".metadata_edit";
2093         if(0 == tempfile_path_prefix) {
2094                 if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) {
2095                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2096                         return false;
2097                 }
2098                 strcpy(*tempfilename, filename);
2099                 strcat(*tempfilename, tempfile_suffix);
2100         }
2101         else {
2102                 const char *p = strrchr(filename, '/');
2103                 if(0 == p)
2104                         p = filename;
2105                 else
2106                         p++;
2107
2108                 if(0 == (*tempfilename = malloc(strlen(tempfile_path_prefix) + 1 + strlen(p) + strlen(tempfile_suffix) + 1))) {
2109                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2110                         return false;
2111                 }
2112                 strcpy(*tempfilename, tempfile_path_prefix);
2113                 strcat(*tempfilename, "/");
2114                 strcat(*tempfilename, p);
2115                 strcat(*tempfilename, tempfile_suffix);
2116         }
2117
2118         if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) {
2119                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
2120                 return false;
2121         }
2122
2123         return true;
2124 }
2125
2126 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
2127 {
2128         FLAC__ASSERT(0 != filename);
2129         FLAC__ASSERT(0 != tempfile);
2130         FLAC__ASSERT(0 != *tempfile);
2131         FLAC__ASSERT(0 != tempfilename);
2132         FLAC__ASSERT(0 != *tempfilename);
2133         FLAC__ASSERT(0 != status);
2134
2135         (void)fclose(*tempfile);
2136         *tempfile = 0;
2137
2138 #if defined _MSC_VER || defined __MINGW32__
2139         if(unlink(filename) < 0) {
2140                 cleanup_tempfile_(tempfile, tempfilename);
2141                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR;
2142                 return false;
2143         }
2144 #endif
2145
2146         /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */
2147         if(0 != rename(*tempfilename, filename)) {
2148                 cleanup_tempfile_(tempfile, tempfilename);
2149                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
2150                 return false;
2151         }
2152
2153         cleanup_tempfile_(tempfile, tempfilename);
2154
2155         return true;
2156 }
2157
2158 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
2159 {
2160         if(0 != *tempfile) {
2161                 (void)fclose(*tempfile);
2162                 *tempfile = 0;
2163         }
2164
2165         if(0 != *tempfilename) {
2166                 (void)unlink(*tempfilename);
2167                 free(*tempfilename);
2168                 *tempfilename = 0;
2169         }
2170 }
2171
2172 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
2173 {
2174         FLAC__ASSERT(0 != filename);
2175         FLAC__ASSERT(0 != stats);
2176         return (0 == stat(filename, stats));
2177 }
2178
2179 void set_file_stats_(const char *filename, struct stat *stats)
2180 {
2181         struct utimbuf srctime;
2182
2183         FLAC__ASSERT(0 != filename);
2184         FLAC__ASSERT(0 != stats);
2185
2186         srctime.actime = stats->st_atime;
2187         srctime.modtime = stats->st_mtime;
2188         (void)chmod(filename, stats->st_mode);
2189         (void)utime(filename, &srctime);
2190 #if !defined _MSC_VER && !defined __MINGW32__
2191         (void)chown(filename, stats->st_uid, -1);
2192         (void)chown(filename, -1, stats->st_gid);
2193 #endif
2194 }
2195
2196 FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)
2197 {
2198         switch(status) {
2199                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK:
2200                         return FLAC__METADATA_CHAIN_STATUS_OK;
2201                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
2202                         return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT;
2203                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
2204                         return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2205                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
2206                         return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
2207                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE:
2208                         return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE;
2209                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA:
2210                         return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
2211                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR:
2212                         return FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
2213                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR:
2214                         return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2215                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR:
2216                         return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
2217                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR:
2218                         return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR;
2219                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR:
2220                         return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR;
2221                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR:
2222                         return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
2223                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR:
2224                 default:
2225                         return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
2226         }
2227 }