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