don't use errno on win32
[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 #endif
312                 else {
313                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
314                         return false;
315                 }
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         unsigned current_length; /*@@@ 4G limit */
717 };
718
719 struct FLAC__Metadata_Iterator {
720         FLAC__Metadata_Chain *chain;
721         FLAC__Metadata_Node *current;
722 };
723
724 const char * const FLAC__Metadata_ChainStatusString[] = {
725         "FLAC__METADATA_CHAIN_STATUS_OK",
726         "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT",
727         "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE",
728         "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE",
729         "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE",
730         "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA",
731         "FLAC__METADATA_CHAIN_STATUS_READ_ERROR",
732         "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR",
733         "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR",
734         "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
735         "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
736         "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
737         "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR"
738 };
739
740
741 static FLAC__Metadata_Node *node_new_()
742 {
743         FLAC__Metadata_Node *node = (FLAC__Metadata_Node*)malloc(sizeof(FLAC__Metadata_Node));
744         if(0 != node)
745                 memset(node, 0, sizeof(FLAC__Metadata_Node));
746         return node;
747 }
748
749 static void node_delete_(FLAC__Metadata_Node *node)
750 {
751         FLAC__ASSERT(0 != node);
752         if(0 != node->data)
753                 FLAC__metadata_object_delete(node->data);
754         free(node);
755 }
756
757 static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
758 {
759         FLAC__ASSERT(0 != chain);
760         FLAC__ASSERT(0 != node);
761         FLAC__ASSERT(0 != node->data);
762
763         node->next = node->prev = 0;
764         node->data->is_last = true;
765         if(0 != chain->tail)
766                 chain->tail->data->is_last = false;
767
768         if(0 == chain->head)
769                 chain->head = node;
770         else {
771                 FLAC__ASSERT(0 != chain->tail);
772                 chain->tail->next = node;
773                 node->prev = chain->tail;
774         }
775         chain->tail = node;
776         chain->nodes++;
777         chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
778 }
779
780 static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
781 {
782         FLAC__ASSERT(0 != chain);
783         FLAC__ASSERT(0 != node);
784
785         if(node == chain->head)
786                 chain->head = node->next;
787         else
788                 node->prev->next = node->next;
789
790         if(node == chain->tail)
791                 chain->tail = node->prev;
792         else
793                 node->next->prev = node->prev;
794
795         if(0 != chain->tail)
796                 chain->tail->data->is_last = true;
797
798         chain->nodes--;
799         chain->current_length -= (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
800 }
801
802 static void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
803 {
804         chain_remove_node_(chain, node);
805         node_delete_(node);
806 }
807
808 static void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
809 {
810         FLAC__ASSERT(0 != node);
811         FLAC__ASSERT(0 != node->data);
812         FLAC__ASSERT(0 != iterator);
813         FLAC__ASSERT(0 != iterator->current);
814         FLAC__ASSERT(0 != iterator->chain);
815         FLAC__ASSERT(0 != iterator->chain->head);
816         FLAC__ASSERT(0 != iterator->chain->tail);
817
818         node->data->is_last = false;
819
820         node->prev = iterator->current->prev;
821         node->next = iterator->current;
822
823         if(0 == node->prev)
824                 iterator->chain->head = node;
825         else
826                 node->prev->next = node;
827
828         iterator->current->prev = node;
829
830         iterator->chain->nodes++;
831         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
832 }
833
834 static void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node)
835 {
836         FLAC__ASSERT(0 != node);
837         FLAC__ASSERT(0 != node->data);
838         FLAC__ASSERT(0 != iterator);
839         FLAC__ASSERT(0 != iterator->current);
840         FLAC__ASSERT(0 != iterator->chain);
841         FLAC__ASSERT(0 != iterator->chain->head);
842         FLAC__ASSERT(0 != iterator->chain->tail);
843
844         iterator->current->data->is_last = false;
845
846         node->prev = iterator->current;
847         node->next = iterator->current->next;
848
849         if(0 == node->next)
850                 iterator->chain->tail = node;
851         else
852                 node->next->prev = node;
853
854         node->prev->next = node;
855
856         iterator->chain->tail->data->is_last = true;
857
858         iterator->chain->nodes++;
859         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
860 }
861
862 /* return true iff node and node->next are both padding */
863 static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
864 {
865         if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) {
866                 const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length;
867                 node->data->length += growth;
868                 chain->current_length += growth;
869
870                 chain_delete_node_(chain, node->next);
871                 return true;
872         }
873         else
874                 return false;
875 }
876
877 FLAC__Metadata_Chain *FLAC__metadata_chain_new()
878 {
879         FLAC__Metadata_Chain *chain = malloc(sizeof(FLAC__Metadata_Chain));
880
881         if(0 != chain) {
882                 chain->filename = 0;
883                 chain->head = chain->tail = 0;
884                 chain->nodes = 0;
885                 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
886                 chain->initial_length = chain->current_length = 0;
887         }
888
889         return chain;
890 }
891
892 void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain)
893 {
894         FLAC__Metadata_Node *node, *next;
895
896         FLAC__ASSERT(0 != chain);
897
898         for(node = chain->head; node; ) {
899                 next = node->next;
900                 node_delete_(node);
901                 node = next;
902         }
903
904         if(0 != chain->filename)
905                 free(chain->filename);
906
907         free(chain);
908 }
909
910 FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain)
911 {
912         FLAC__Metadata_ChainStatus status;
913
914         FLAC__ASSERT(0 != chain);
915
916         status = chain->status;
917         chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
918         return status;
919 }
920
921 FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
922 {
923         FLAC__Metadata_SimpleIterator *iterator;
924         FLAC__Metadata_Node *node;
925
926         FLAC__ASSERT(0 != chain);
927         FLAC__ASSERT(0 != filename);
928
929         if(0 == (chain->filename = strdup(filename))) {
930                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
931                 return false;
932         }
933
934         if(0 == (iterator = FLAC__metadata_simple_iterator_new())) {
935                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
936                 return false;
937         }
938
939         if(!FLAC__metadata_simple_iterator_init(iterator, filename, /*preserve_file_stats=*/false)) {
940                 chain->status = get_equivalent_status_(iterator->status);
941                 return false;
942         }
943
944         chain->first_offset = iterator->offset[iterator->depth];
945
946         do {
947                 node = node_new_();
948                 if(0 == node) {
949                         chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
950                         return false;
951                 }
952                 node->data = FLAC__metadata_simple_iterator_get_block(iterator);
953                 if(0 == node->data) {
954                         node_delete_(node);
955                         chain->status = get_equivalent_status_(iterator->status);
956                         return false;
957                 }
958                 chain_append_node_(chain, node);
959         } while(FLAC__metadata_simple_iterator_next(iterator));
960
961         if(!iterator->is_last || iterator->status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) {
962                 chain->status = get_equivalent_status_(iterator->status);
963                 return false;
964         }
965
966         chain->last_offset = ftell(iterator->file) + iterator->length;
967         FLAC__metadata_simple_iterator_delete(iterator);
968
969         chain->initial_length = chain->current_length;
970         return true;
971 }
972
973 FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
974 {
975         struct stat stats;
976         const char *tempfile_path_prefix = 0;
977
978         if(use_padding) {
979                 if(chain->current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
980                         const unsigned delta = chain->initial_length - chain->current_length;
981                         chain->tail->data->length += delta;
982                         chain->current_length += delta;
983                         FLAC__ASSERT(chain->current_length == chain->initial_length);
984                 }
985                 else if(chain->current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
986                         FLAC__StreamMetadata *padding;
987                         FLAC__Metadata_Node *node;
988                         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
989                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
990                                 return false;
991                         }
992                         padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + chain->current_length);
993                         if(0 == (node = node_new_())) {
994                                 FLAC__metadata_object_delete(padding);
995                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
996                                 return false;
997                         }
998                         node->data = padding;
999                         chain_append_node_(chain, node);
1000                         FLAC__ASSERT(chain->current_length == chain->initial_length);
1001                 }
1002                 else if(chain->current_length > chain->initial_length) {
1003                         const unsigned delta = chain->current_length - chain->initial_length;
1004                         if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1005                                 if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
1006                                         chain_delete_node_(chain, chain->tail);
1007                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
1008                                 }
1009                                 else if(chain->tail->data->length >= delta) {
1010                                         chain->tail->data->length -= delta;
1011                                         chain->current_length -= delta;
1012                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
1013                                 }
1014                         }
1015                 }
1016         }
1017
1018         if(preserve_file_stats)
1019                 get_file_stats_(chain->filename, &stats);
1020
1021         if(chain->current_length == chain->initial_length) {
1022                 if(!chain_rewrite_chain_(chain))
1023                         return false;
1024         }
1025         else {
1026                 if(!chain_rewrite_file_(chain, tempfile_path_prefix))
1027                         return false;
1028         }
1029
1030         if(preserve_file_stats)
1031                 set_file_stats_(chain->filename, &stats);
1032
1033         /* recompute lengths and offsets if necessary */
1034         if(chain->initial_length != chain->current_length) {
1035                 const FLAC__Metadata_Node *node;
1036                 chain->initial_length = chain->current_length;
1037                 chain->last_offset = chain->first_offset;
1038                 for(node = chain->head; node; node = node->next)
1039                         chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1040         }
1041
1042         return true;
1043 }
1044
1045 void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain)
1046 {
1047         FLAC__Metadata_Node *node;
1048
1049         FLAC__ASSERT(0 != chain);
1050
1051         for(node = chain->head; node; ) {
1052                 if(!chain_merge_adjacent_padding_(chain, node))
1053                         node = node->next;
1054         }
1055 }
1056
1057 void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain)
1058 {
1059         FLAC__Metadata_Node *node, *save;
1060         unsigned i;
1061
1062         FLAC__ASSERT(0 != chain);
1063
1064         /*
1065          * Don't try and be too smart... this simple algo is good enough for
1066          * the small number of nodes that we deal with.
1067          */
1068         for(i = 0, node = chain->head; i < chain->nodes; i++) {
1069                 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1070                         save = node->next;
1071                         chain_remove_node_(chain, node);
1072                         chain_append_node_(chain, node);
1073                         node = save;
1074                 }
1075                 else {
1076                         node = node->next;
1077                 }
1078         }
1079
1080         FLAC__metadata_chain_merge_padding(chain);
1081 }
1082
1083
1084 FLAC__Metadata_Iterator *FLAC__metadata_iterator_new()
1085 {
1086         FLAC__Metadata_Iterator *iterator = malloc(sizeof(FLAC__Metadata_Iterator));
1087
1088         if(0 != iterator) {
1089                 iterator->current = 0;
1090                 iterator->chain = 0;
1091         }
1092
1093         return iterator;
1094 }
1095
1096 void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator)
1097 {
1098         FLAC__ASSERT(0 != iterator);
1099
1100         free(iterator);
1101 }
1102
1103 /*
1104  * Initialize the iterator to point to the first metadata block in the
1105  * given chain.
1106  */
1107 void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain)
1108 {
1109         FLAC__ASSERT(0 != iterator);
1110         FLAC__ASSERT(0 != chain);
1111         FLAC__ASSERT(0 != chain->head);
1112
1113         iterator->chain = chain;
1114         iterator->current = chain->head;
1115 }
1116
1117 FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator)
1118 {
1119         FLAC__ASSERT(0 != iterator);
1120
1121         if(0 == iterator->current || 0 == iterator->current->next)
1122                 return false;
1123
1124         iterator->current = iterator->current->next;
1125         return true;
1126 }
1127
1128 FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator)
1129 {
1130         FLAC__ASSERT(0 != iterator);
1131
1132         if(0 == iterator->current || 0 == iterator->current->prev)
1133                 return false;
1134
1135         iterator->current = iterator->current->prev;
1136         return true;
1137 }
1138
1139 FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator)
1140 {
1141         FLAC__ASSERT(0 != iterator);
1142         FLAC__ASSERT(0 != iterator->current);
1143         FLAC__ASSERT(0 != iterator->current->data);
1144
1145         return iterator->current->data->type;
1146 }
1147
1148 FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator)
1149 {
1150         FLAC__ASSERT(0 != iterator);
1151         FLAC__ASSERT(0 != iterator->current);
1152
1153         return iterator->current->data;
1154 }
1155
1156 FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1157 {
1158         return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
1159 }
1160
1161 FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding)
1162 {
1163         FLAC__Metadata_Node *save;
1164
1165         FLAC__ASSERT(0 != iterator);
1166         FLAC__ASSERT(0 != iterator->current);
1167
1168         if(0 == iterator->current->prev) {
1169                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1170                 return false;
1171         }
1172
1173         save = iterator->current->prev;
1174
1175         if(replace_with_padding) {
1176                 FLAC__metadata_object_delete_data(iterator->current->data);
1177                 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
1178         }
1179         else {
1180                 chain_delete_node_(iterator->chain, iterator->current);
1181         }
1182
1183         iterator->current = save;
1184         return true;
1185 }
1186
1187 FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1188 {
1189         FLAC__Metadata_Node *node;
1190
1191         FLAC__ASSERT(0 != iterator);
1192         FLAC__ASSERT(0 != iterator->current);
1193
1194         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1195                 return false;
1196
1197         if(0 == iterator->current->prev) {
1198                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1199                 return false;
1200         }
1201
1202         if(0 == (node = node_new_()))
1203                 return false;
1204
1205         node->data = block;
1206         iterator_insert_node_(iterator, node);
1207         iterator->current = node;
1208         return true;
1209 }
1210
1211 FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
1212 {
1213         FLAC__Metadata_Node *node;
1214
1215         FLAC__ASSERT(0 != iterator);
1216         FLAC__ASSERT(0 != iterator->current);
1217
1218         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1219                 return false;
1220
1221         if(0 == (node = node_new_()))
1222                 return false;
1223
1224         node->data = block;
1225         iterator_insert_node_after_(iterator, node);
1226         iterator->current = node;
1227         return true;
1228 }
1229
1230
1231 /****************************************************************************
1232  *
1233  * Local function definitions
1234  *
1235  ***************************************************************************/
1236
1237 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1238 {
1239         unsigned i;
1240
1241         b += bytes;
1242
1243         for(i = 0; i < bytes; i++) {
1244                 *(--b) = (FLAC__byte)(val & 0xff);
1245                 val >>= 8;
1246         }
1247 }
1248
1249 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1250 {
1251         unsigned i;
1252
1253         for(i = 0; i < bytes; i++) {
1254                 *(b++) = (FLAC__byte)(val & 0xff);
1255                 val >>= 8;
1256         }
1257 }
1258
1259 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes)
1260 {
1261         unsigned i;
1262
1263         b += bytes;
1264
1265         for(i = 0; i < bytes; i++) {
1266                 *(--b) = (FLAC__byte)(val & 0xff);
1267                 val >>= 8;
1268         }
1269 }
1270
1271 FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes)
1272 {
1273         FLAC__uint32 ret = 0;
1274         unsigned i;
1275
1276         for(i = 0; i < bytes; i++)
1277                 ret = (ret << 8) | (FLAC__uint32)(*b++);
1278
1279         return ret;
1280 }
1281
1282 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes)
1283 {
1284         FLAC__uint32 ret = 0;
1285         unsigned i;
1286
1287         b += bytes;
1288
1289         for(i = 0; i < bytes; i++)
1290                 ret = (ret << 8) | (FLAC__uint32)(*--b);
1291
1292         return ret;
1293 }
1294
1295 FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes)
1296 {
1297         FLAC__uint64 ret = 0;
1298         unsigned i;
1299
1300         for(i = 0; i < bytes; i++)
1301                 ret = (ret << 8) | (FLAC__uint64)(*b++);
1302
1303         return ret;
1304 }
1305
1306 FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator)
1307 {
1308         FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
1309
1310         FLAC__ASSERT(0 != iterator);
1311         FLAC__ASSERT(0 != iterator->file);
1312
1313         if(fread(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, iterator->file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1314                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1315                 return false;
1316         }
1317
1318         iterator->is_last = raw_header[0] & 0x80? true : false;
1319         iterator->type = (FLAC__MetadataType)(raw_header[0] & 0x7f);
1320         iterator->length = unpack_uint32_(raw_header + 1, 3);
1321
1322         /* do some checking */
1323         if(iterator->type > FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1324                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
1325                 return false;
1326         }
1327
1328         return true;
1329 }
1330
1331 FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block)
1332 {
1333         FLAC__ASSERT(0 != iterator);
1334         FLAC__ASSERT(0 != iterator->file);
1335
1336         switch(block->type) {
1337                 case FLAC__METADATA_TYPE_STREAMINFO:
1338                         iterator->status = read_metadata_block_data_streaminfo_(iterator->file, &block->data.stream_info);
1339                         break;
1340                 case FLAC__METADATA_TYPE_PADDING:
1341                         iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length);
1342                         break;
1343                 case FLAC__METADATA_TYPE_APPLICATION:
1344                         iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length);
1345                         break;
1346                 case FLAC__METADATA_TYPE_SEEKTABLE:
1347                         iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length);
1348                         break;
1349                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1350                         iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment);
1351                         break;
1352                 default:
1353                         FLAC__ASSERT(0);
1354                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1355         }
1356
1357         return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1358 }
1359
1360 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block)
1361 {
1362         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
1363
1364         FLAC__ASSERT(0 != file);
1365
1366         if(fread(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1367                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1368
1369         b = buffer;
1370
1371         /* @@@ we are using hardcoded numbers for simplicity but we should
1372          * probably eventually write a bit-level unpacker and use the
1373          * _STREAMINFO_ constants.
1374          */
1375         block->min_blocksize = unpack_uint32_(b, 2); b += 2;
1376         block->max_blocksize = unpack_uint32_(b, 2); b += 2;
1377         block->min_framesize = unpack_uint32_(b, 3); b += 3;
1378         block->max_framesize = unpack_uint32_(b, 3); b += 3;
1379         block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
1380         block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
1381         block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 1) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
1382         block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
1383         memcpy(block->md5sum, b+8, 16);
1384
1385         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1386 }
1387
1388
1389 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetadata_Padding *block, unsigned block_length)
1390 {
1391         FLAC__ASSERT(0 != file);
1392
1393         (void)block; /* nothing to do; we don't care about reading the padding bytes */
1394
1395         if(0 != fseek(file, block_length, SEEK_CUR))
1396                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1397
1398         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1399 }
1400
1401 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetadata_Application *block, unsigned block_length)
1402 {
1403         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1404
1405         FLAC__ASSERT(0 != file);
1406
1407         if(fread(block->id, 1, id_bytes, file) != id_bytes)
1408                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1409
1410         block_length -= id_bytes;
1411
1412         if(block_length == 0) {
1413                 block->data = 0;
1414         }
1415         else {
1416                 if(0 == (block->data = malloc(block_length)))
1417                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1418
1419                 if(fread(block->data, 1, block_length, file) != block_length)
1420                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1421         }
1422
1423         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1424 }
1425
1426 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetadata_SeekTable *block, unsigned block_length)
1427 {
1428         unsigned i;
1429         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1430
1431         FLAC__ASSERT(0 != file);
1432         FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0);
1433
1434         block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1435
1436         if(block->num_points == 0)
1437                 block->points = 0;
1438         else if(0 == (block->points = malloc(block->num_points * sizeof(FLAC__StreamMetadata_SeekPoint))))
1439                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1440
1441         for(i = 0; i < block->num_points; i++) {
1442                 if(fread(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1443                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1444                 /*@@@ some MAGIC NUMBERs here */
1445                 block->points[i].sample_number = unpack_uint64_(buffer, 8);
1446                 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
1447                 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
1448         }
1449
1450         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1451 }
1452
1453 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetadata_VorbisComment_Entry *entry)
1454 {
1455         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1456         FLAC__byte buffer[4]; /* magic number is asserted below */
1457
1458         FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
1459         FLAC__ASSERT(0 != file);
1460
1461         if(fread(buffer, 1, entry_length_len, file) != entry_length_len)
1462                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1463         entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
1464
1465         if(entry->length == 0) {
1466                 entry->entry = 0;
1467         }
1468         else {
1469                 if(0 == (entry->entry = malloc(entry->length)))
1470                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1471
1472                 if(fread(entry->entry, 1, entry->length, file) != entry->length)
1473                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1474         }
1475
1476         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1477 }
1478
1479 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block)
1480 {
1481         unsigned i;
1482         FLAC__Metadata_SimpleIteratorStatus status;
1483         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1484         FLAC__byte buffer[4]; /* magic number is asserted below */
1485
1486         FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
1487         FLAC__ASSERT(0 != file);
1488
1489         if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, &(block->vendor_string))))
1490                 return status;
1491
1492         if(fread(buffer, 1, num_comments_len, file) != num_comments_len)
1493                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1494         block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
1495
1496         if(block->num_comments == 0) {
1497                 block->comments = 0;
1498         }
1499         else if(0 == (block->comments = malloc(block->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry))))
1500                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1501
1502         for(i = 0; i < block->num_comments; i++) {
1503                 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, block->comments + i)))
1504                         return status;
1505         }
1506
1507         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1508 }
1509
1510 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
1511 {
1512         FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
1513
1514         FLAC__ASSERT(0 != file);
1515         FLAC__ASSERT(0 != status);
1516         FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
1517
1518         buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type;
1519         pack_uint32_(block->length, buffer + 1, 3);
1520
1521         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1522                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1523                 return false;
1524         }
1525
1526         return true;
1527 }
1528
1529 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
1530 {
1531         FLAC__ASSERT(0 != file);
1532         FLAC__ASSERT(0 != status);
1533
1534         switch(block->type) {
1535                 case FLAC__METADATA_TYPE_STREAMINFO:
1536                         *status = write_metadata_block_data_streaminfo_(file, &block->data.stream_info);
1537                         break;
1538                 case FLAC__METADATA_TYPE_PADDING:
1539                         *status = write_metadata_block_data_padding_(file, &block->data.padding, block->length);
1540                         break;
1541                 case FLAC__METADATA_TYPE_APPLICATION:
1542                         *status = write_metadata_block_data_application_(file, &block->data.application, block->length);
1543                         break;
1544                 case FLAC__METADATA_TYPE_SEEKTABLE:
1545                         *status = write_metadata_block_data_seektable_(file, &block->data.seek_table);
1546                         break;
1547                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1548                         *status = write_metadata_block_data_vorbis_comment_(file, &block->data.vorbis_comment);
1549                         break;
1550                 default:
1551                         FLAC__ASSERT(0);
1552                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1553         }
1554         return (*status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1555 }
1556
1557 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetadata_StreamInfo *block)
1558 {
1559         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
1560         const unsigned channels1 = block->channels - 1;
1561         const unsigned bps1 = block->bits_per_sample - 1;
1562
1563         FLAC__ASSERT(0 != file);
1564
1565         /* @@@ we are using hardcoded numbers for simplicity but we should
1566          * probably eventually write a bit-level packer and use the
1567          * _STREAMINFO_ constants.
1568          */
1569         pack_uint32_(block->min_blocksize, buffer, 2);
1570         pack_uint32_(block->max_blocksize, buffer+2, 2);
1571         pack_uint32_(block->min_framesize, buffer+4, 3);
1572         pack_uint32_(block->max_framesize, buffer+7, 3);
1573         buffer[10] = (block->sample_rate >> 12) & 0xff;
1574         buffer[11] = (block->sample_rate >> 4) & 0xff;
1575         buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4);
1576         buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f));
1577         pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4);
1578         memcpy(buffer+18, block->md5sum, 16);
1579
1580         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1581                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1582
1583         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1584 }
1585
1586 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetadata_Padding *block, unsigned block_length)
1587 {
1588         unsigned i, n = block_length;
1589         FLAC__byte buffer[1024];
1590
1591         FLAC__ASSERT(0 != file);
1592
1593         (void)block;
1594
1595         memset(buffer, 0, 1024);
1596
1597         for(i = 0; i < n/1024; i++)
1598                 if(fwrite(buffer, 1, 1024, file) != 1024)
1599                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1600
1601         n %= 1024;
1602         
1603         if(fwrite(buffer, 1, n, file) != n)
1604                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1605
1606         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1607 }
1608
1609 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetadata_Application *block, unsigned block_length)
1610 {
1611         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1612
1613         FLAC__ASSERT(0 != file);
1614
1615         if(fwrite(block->id, 1, id_bytes, file) != id_bytes)
1616                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1617
1618         block_length -= id_bytes;
1619
1620         if(fwrite(block->data, 1, block_length, file) != block_length)
1621                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1622
1623         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1624 }
1625
1626 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetadata_SeekTable *block)
1627 {
1628         unsigned i;
1629         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1630
1631         FLAC__ASSERT(0 != file);
1632
1633         for(i = 0; i < block->num_points; i++) {
1634                 /*@@@ some MAGIC NUMBERs here */
1635                 pack_uint64_(block->points[i].sample_number, buffer, 8);
1636                 pack_uint64_(block->points[i].stream_offset, buffer+8, 8);
1637                 pack_uint32_(block->points[i].frame_samples, buffer+16, 2);
1638                 if(fwrite(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1639                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1640         }
1641
1642         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1643 }
1644
1645 FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetadata_VorbisComment *block)
1646 {
1647         unsigned i;
1648         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1649         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1650         FLAC__byte buffer[4]; /* magic number is asserted below */
1651
1652         FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == 4);
1653         FLAC__ASSERT(0 != file);
1654
1655         pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
1656         if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
1657                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1658         if(fwrite(block->vendor_string.entry, 1, block->vendor_string.length, file) != block->vendor_string.length)
1659                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1660
1661         pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len);
1662         if(fwrite(buffer, 1, num_comments_len, file) != num_comments_len)
1663                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1664
1665         for(i = 0; i < block->num_comments; i++) {
1666                 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len);
1667                 if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
1668                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1669                 if(fwrite(block->comments[i].entry, 1, block->comments[i].length, file) != block->comments[i].length)
1670                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1671         }
1672
1673         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1674 }
1675
1676 FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block)
1677 {
1678         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1679                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1680                 return false;
1681         }
1682
1683         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
1684                 return false;
1685
1686         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
1687                 return false;
1688
1689         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1690                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1691                 return false;
1692         }
1693
1694         return read_metadata_block_header_(iterator);
1695 }
1696
1697 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last)
1698 {
1699         FLAC__StreamMetadata *padding;
1700
1701         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1702                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1703                 return false;
1704         }
1705
1706         block->is_last = false;
1707
1708         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
1709                 return false;
1710
1711         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
1712                 return false;
1713
1714         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1715                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1716
1717         padding->is_last = padding_is_last;
1718         padding->length = padding_length;
1719
1720         if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) {
1721                 FLAC__metadata_object_delete(padding);
1722                 return false;
1723         }
1724
1725         if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) {
1726                 FLAC__metadata_object_delete(padding);
1727                 return false;
1728         }
1729
1730         FLAC__metadata_object_delete(padding);
1731
1732         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1733                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1734                 return false;
1735         }
1736
1737         return read_metadata_block_header_(iterator);
1738 }
1739
1740 FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append)
1741 {
1742         FILE *tempfile;
1743         char *tempfilename;
1744         int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
1745         long fixup_is_last_flag_offset = -1;
1746
1747         FLAC__ASSERT(0 != block || append == false);
1748
1749         if(iterator->is_last) {
1750                 if(append) {
1751                         fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */
1752                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
1753                 }
1754                 else if(0 == block) {
1755                         simple_iterator_push_(iterator);
1756                         if(!FLAC__metadata_simple_iterator_prev(iterator)) {
1757                                 (void)simple_iterator_pop_(iterator);
1758                                 return false;
1759                         }
1760                         fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */
1761                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
1762                         if(!simple_iterator_pop_(iterator))
1763                                 return false;
1764                 }
1765         }
1766
1767         if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append))
1768                 return false;
1769
1770         if(0 != block) {
1771                 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) {
1772                         cleanup_tempfile_(&tempfile, &tempfilename);
1773                         return false;
1774                 }
1775
1776                 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) {
1777                         cleanup_tempfile_(&tempfile, &tempfilename);
1778                         return false;
1779                 }
1780         }
1781
1782         if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0))
1783                 return false;
1784
1785         if(append)
1786                 return FLAC__metadata_simple_iterator_next(iterator);
1787
1788         return true;
1789 }
1790
1791 FLAC__bool chain_rewrite_chain_(FLAC__Metadata_Chain *chain)
1792 {
1793         FILE *f;
1794         FLAC__Metadata_Node *node;
1795         FLAC__Metadata_SimpleIteratorStatus status;
1796
1797         FLAC__ASSERT(0 != chain);
1798         FLAC__ASSERT(0 != chain->filename);
1799         FLAC__ASSERT(0 != chain->head);
1800
1801         if(0 == (f = fopen(chain->filename, "r+b"))) {
1802                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1803                 return false;
1804         }
1805         if(0 != fseek(f, chain->first_offset, SEEK_SET)) {
1806                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1807                 return false;
1808         }
1809
1810         for(node = chain->head; node; node = node->next) {
1811                 if(!write_metadata_block_header_(f, &status, node->data)) {
1812                         chain->status = get_equivalent_status_(status);
1813                         return false;
1814                 }
1815                 if(!write_metadata_block_data_(f, &status, node->data)) {
1816                         chain->status = get_equivalent_status_(status);
1817                         return false;
1818                 }
1819         }
1820
1821         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
1822
1823         (void)fclose(f);
1824
1825         return true;
1826 }
1827
1828 FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix)
1829 {
1830         FILE *f, *tempfile;
1831         char *tempfilename;
1832         FLAC__Metadata_SimpleIteratorStatus status;
1833         const FLAC__Metadata_Node *node;
1834
1835         FLAC__ASSERT(0 != chain);
1836         FLAC__ASSERT(0 != chain->filename);
1837         FLAC__ASSERT(0 != chain->head);
1838
1839         /* copy the file prefix (data up to first metadata block */
1840         if(0 == (f = fopen(chain->filename, "rb"))) {
1841                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1842                 return false;
1843         }
1844         if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) {
1845                 chain->status = get_equivalent_status_(status);
1846                 cleanup_tempfile_(&tempfile, &tempfilename);
1847                 return false;
1848         }
1849         if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) {
1850                 chain->status = get_equivalent_status_(status);
1851                 cleanup_tempfile_(&tempfile, &tempfilename);
1852                 return false;
1853         }
1854
1855         /* write the metadata */
1856         for(node = chain->head; node; node = node->next) {
1857                 if(!write_metadata_block_header_(tempfile, &status, node->data)) {
1858                         chain->status = get_equivalent_status_(status);
1859                         return false;
1860                 }
1861                 if(!write_metadata_block_data_(tempfile, &status, node->data)) {
1862                         chain->status = get_equivalent_status_(status);
1863                         return false;
1864                 }
1865         }
1866         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
1867
1868         /* copy the file postfix (everything after the metadata) */
1869         if(0 != fseek(f, chain->last_offset, SEEK_SET)) {
1870                 cleanup_tempfile_(&tempfile, &tempfilename);
1871                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1872                 return false;
1873         }
1874         if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) {
1875                 cleanup_tempfile_(&tempfile, &tempfilename);
1876                 chain->status = get_equivalent_status_(status);
1877                 return false;
1878         }
1879
1880         /* move the tempfile on top of the original */
1881         (void)fclose(f);
1882         if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
1883                 return false;
1884
1885         return true;
1886 }
1887
1888 void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator)
1889 {
1890         FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH);
1891         iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth];
1892         iterator->depth++;
1893 }
1894
1895 FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator)
1896 {
1897         FLAC__ASSERT(iterator->depth > 0);
1898         iterator->depth--;
1899         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
1900                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1901                 return false;
1902         }
1903
1904         return read_metadata_block_header_(iterator);
1905 }
1906
1907 unsigned seek_to_first_metadata_block_(FILE *f)
1908 {
1909         FLAC__byte buffer[4];
1910         size_t n;
1911         unsigned i;
1912
1913         FLAC__ASSERT(0 != f);
1914         FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
1915
1916         /* skip any id3v2 tag */
1917 #if !defined _MSC_VER && !defined __MINGW32__
1918 /*@@@ don't know how to resolve errno without using LIBC.LIB; must use MSVCRT.LIB only for plugins */
1919         errno = 0;
1920 #endif
1921         n = fread(buffer, 1, 4, f);
1922 #if !defined _MSC_VER && !defined __MINGW32__
1923 /*@@@ don't know how to resolve errno without using LIBC.LIB; must use MSVCRT.LIB only for plugins */
1924         if(errno)
1925                 return 1;
1926         else
1927 #endif
1928         if(n != 4)
1929                 return 2;
1930         else if(0 == memcmp(buffer, "ID3", 3)) {
1931                 unsigned tag_length = 0;
1932
1933                 /* skip to the tag length */
1934                 if(fseek(f, 2, SEEK_CUR) < 0)
1935                         return 1;
1936
1937                 /* read the length */
1938                 for(i = 0; i < 4; i++) {
1939                         if(fread(buffer, 1, 1, f) < 1 || buffer[0] & 0x80)
1940                                 return 1;
1941                         tag_length <<= 7;
1942                         tag_length |= (buffer[0] & 0x7f);
1943                 }
1944
1945                 /* skip the rest of the tag */
1946                 if(fseek(f, tag_length, SEEK_CUR) < 0)
1947                         return 1;
1948
1949                 /* read the stream sync code */
1950 #if !defined _MSC_VER && !defined __MINGW32__
1951 /*@@@ don't know how to resolve errno without using LIBC.LIB; must use MSVCRT.LIB only for plugins */
1952                 errno = 0;
1953 #endif
1954                 n = fread(buffer, 1, 4, f);
1955 #if !defined _MSC_VER && !defined __MINGW32__
1956 /*@@@ don't know how to resolve errno without using LIBC.LIB; must use MSVCRT.LIB only for plugins */
1957                 if(errno)
1958                         return 1;
1959                 else
1960 #endif
1961                 if(n != 4)
1962                         return 2;
1963         }
1964
1965         /* check for the fLaC signature */
1966         if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH))
1967                 return 0;
1968         else
1969                 return 2;
1970 }
1971
1972 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
1973 {
1974         const long offset_end = append? iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length : iterator->offset[iterator->depth];
1975
1976         if(0 != fseek(iterator->file, 0, SEEK_SET)) {
1977                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1978                 return false;
1979         }
1980         if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) {
1981                 cleanup_tempfile_(tempfile, tempfilename);
1982                 return false;
1983         }
1984         if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) {
1985                 cleanup_tempfile_(tempfile, tempfilename);
1986                 return false;
1987         }
1988
1989         return true;
1990 }
1991
1992 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)
1993 {
1994         long save_offset = iterator->offset[iterator->depth]; /*@@@ 2G limit */
1995         FLAC__ASSERT(0 != *tempfile);
1996
1997         if(0 != fseek(iterator->file, save_offset + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length, SEEK_SET)) {
1998                 cleanup_tempfile_(tempfile, tempfilename);
1999                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2000                 return false;
2001         }
2002         if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) {
2003                 cleanup_tempfile_(tempfile, tempfilename);
2004                 return false;
2005         }
2006
2007         if(fixup_is_last_code != 0) {
2008                 /*
2009                  * if code == 1, it means a block was appended to the end so
2010                  *   we have to clear the is_last flag of the previous block
2011                  * if code == -1, it means the last block was deleted so
2012                  *   we have to set the is_last flag of the previous block
2013                  */
2014                 /*@@@ MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
2015                 FLAC__byte x;
2016                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2017                         cleanup_tempfile_(tempfile, tempfilename);
2018                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2019                         return false;
2020                 }
2021                 if(fread(&x, 1, 1, *tempfile) != 1) {
2022                         cleanup_tempfile_(tempfile, tempfilename);
2023                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2024                         return false;
2025                 }
2026                 if(fixup_is_last_code > 0) {
2027                         FLAC__ASSERT(x & 0x80);
2028                         x &= 0x7f;
2029                 }
2030                 else {
2031                         FLAC__ASSERT(!(x & 0x80));
2032                         x |= 0x80;
2033                 }
2034                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2035                         cleanup_tempfile_(tempfile, tempfilename);
2036                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2037                         return false;
2038                 }
2039                 if(fwrite(&x, 1, 1, *tempfile) != 1) {
2040                         cleanup_tempfile_(tempfile, tempfilename);
2041                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2042                         return false;
2043                 }
2044         }
2045
2046         (void)fclose(iterator->file);
2047
2048         if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status))
2049                 return false;
2050
2051         if(iterator->has_stats)
2052                 set_file_stats_(iterator->filename, &iterator->stats);
2053
2054         if(!simple_iterator_prime_input_(iterator))
2055                 return false;
2056         if(backup) {
2057                 while(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length < save_offset)
2058                         if(!FLAC__metadata_simple_iterator_next(iterator))
2059                                 return false;
2060                 return true;
2061         }
2062         else {
2063                 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */
2064                 FLAC__ASSERT(iterator->depth == 0);
2065                 iterator->offset[0] = save_offset;
2066                 iterator->depth++;
2067                 return simple_iterator_pop_(iterator);
2068         }
2069 }
2070
2071 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status)
2072 {
2073         FLAC__byte buffer[8192];
2074         unsigned n;
2075
2076         while(bytes > 0) {
2077                 n = min(sizeof(buffer), bytes);
2078                 if(fread(buffer, 1, n, file) != n) {
2079                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2080                         return false;
2081                 }
2082                 if(fwrite(buffer, 1, n, tempfile) != n) {
2083                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2084                         return false;
2085                 }
2086                 bytes -= n;
2087         }
2088
2089         return true;
2090 }
2091
2092 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status)
2093 {
2094         FLAC__byte buffer[8192];
2095         size_t n;
2096
2097         while(!feof(file)) {
2098                 n = fread(buffer, 1, sizeof(buffer), file);
2099                 if(n == 0 && !feof(file)) {
2100                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2101                         return false;
2102                 }
2103                 if(n > 0 && fwrite(buffer, 1, n, tempfile) != n) {
2104                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2105                         return false;
2106                 }
2107         }
2108
2109         return true;
2110 }
2111
2112 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
2113 {
2114         static const char *tempfile_suffix = ".metadata_edit";
2115         if(0 == tempfile_path_prefix) {
2116                 if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) {
2117                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2118                         return false;
2119                 }
2120                 strcpy(*tempfilename, filename);
2121                 strcat(*tempfilename, tempfile_suffix);
2122         }
2123         else {
2124                 const char *p = strrchr(filename, '/');
2125                 if(0 == p)
2126                         p = filename;
2127                 else
2128                         p++;
2129
2130                 if(0 == (*tempfilename = malloc(strlen(tempfile_path_prefix) + 1 + strlen(p) + strlen(tempfile_suffix) + 1))) {
2131                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2132                         return false;
2133                 }
2134                 strcpy(*tempfilename, tempfile_path_prefix);
2135                 strcat(*tempfilename, "/");
2136                 strcat(*tempfilename, p);
2137                 strcat(*tempfilename, tempfile_suffix);
2138         }
2139
2140         if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) {
2141                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
2142                 return false;
2143         }
2144
2145         return true;
2146 }
2147
2148 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status)
2149 {
2150         FLAC__ASSERT(0 != filename);
2151         FLAC__ASSERT(0 != tempfile);
2152         FLAC__ASSERT(0 != *tempfile);
2153         FLAC__ASSERT(0 != tempfilename);
2154         FLAC__ASSERT(0 != *tempfilename);
2155         FLAC__ASSERT(0 != status);
2156
2157         (void)fclose(*tempfile);
2158         *tempfile = 0;
2159
2160 #if defined _MSC_VER || defined __MINGW32__
2161         if(unlink(filename) < 0) {
2162                 cleanup_tempfile_(tempfile, tempfilename);
2163                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR;
2164                 return false;
2165         }
2166 #endif
2167
2168         /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */
2169         if(0 != rename(*tempfilename, filename)) {
2170                 cleanup_tempfile_(tempfile, tempfilename);
2171                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
2172                 return false;
2173         }
2174
2175         cleanup_tempfile_(tempfile, tempfilename);
2176
2177         return true;
2178 }
2179
2180 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
2181 {
2182         if(0 != *tempfile) {
2183                 (void)fclose(*tempfile);
2184                 *tempfile = 0;
2185         }
2186
2187         if(0 != *tempfilename) {
2188                 (void)unlink(*tempfilename);
2189                 free(*tempfilename);
2190                 *tempfilename = 0;
2191         }
2192 }
2193
2194 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
2195 {
2196         FLAC__ASSERT(0 != filename);
2197         FLAC__ASSERT(0 != stats);
2198         return (0 == stat(filename, stats));
2199 }
2200
2201 void set_file_stats_(const char *filename, struct stat *stats)
2202 {
2203         struct utimbuf srctime;
2204
2205         FLAC__ASSERT(0 != filename);
2206         FLAC__ASSERT(0 != stats);
2207
2208         srctime.actime = stats->st_atime;
2209         srctime.modtime = stats->st_mtime;
2210         (void)chmod(filename, stats->st_mode);
2211         (void)utime(filename, &srctime);
2212 #if !defined _MSC_VER && !defined __MINGW32__
2213         (void)chown(filename, stats->st_uid, -1);
2214         (void)chown(filename, -1, stats->st_gid);
2215 #endif
2216 }
2217
2218 FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)
2219 {
2220         switch(status) {
2221                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK:
2222                         return FLAC__METADATA_CHAIN_STATUS_OK;
2223                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
2224                         return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT;
2225                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
2226                         return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2227                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
2228                         return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
2229                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE:
2230                         return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE;
2231                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA:
2232                         return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
2233                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR:
2234                         return FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
2235                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR:
2236                         return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2237                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR:
2238                         return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
2239                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR:
2240                         return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR;
2241                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR:
2242                         return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR;
2243                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR:
2244                         return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
2245                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR:
2246                 default:
2247                         return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
2248         }
2249 }