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