a53891c98172f263383983988c2801678289fff2
[flac.git] / src / libFLAC / metadata.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2001,2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 #else
29 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
30 #include <utime.h> /* for utime() */
31 #include <unistd.h> /* for chown(), unlink() */
32 #endif
33 #include <sys/stat.h> /* for stat(), maybe chmod() */
34
35 #include "FLAC/assert.h"
36 #include "FLAC/metadata.h"
37 #include "FLAC/file_decoder.h"
38
39 #ifdef max
40 #undef max
41 #endif
42 #define max(a,b) ((a)>(b)?(a):(b))
43 #ifdef min
44 #undef min
45 #endif
46 #define min(a,b) ((a)<(b)?(a):(b))
47
48
49 /****************************************************************************
50  *
51  * Local function declarations
52  *
53  ***************************************************************************/
54
55 /* this one should probably not go in the public interface: */
56 static void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object);
57
58 static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
59 static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
60 static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes);
61 static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes);
62 static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes);
63 static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes);
64
65 static FLAC__bool read_metadata_block_header_(FLAC__MetaData_SimpleIterator *iterator);
66 static FLAC__bool read_metadata_block_data_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block);
67 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetaData_StreamInfo *block);
68 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetaData_Padding *block, unsigned block_length);
69 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetaData_Application *block, unsigned block_length);
70 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetaData_SeekTable *block, unsigned block_length);
71 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetaData_VorbisComment_Entry *entry);
72 static FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetaData_VorbisComment *block);
73
74 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block);
75 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block);
76 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetaData_StreamInfo *block);
77 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetaData_Padding *block, unsigned block_length);
78 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetaData_Application *block, unsigned block_length);
79 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetaData_SeekTable *block);
80 static FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetaData_VorbisComment *block);
81 static FLAC__bool write_metadata_block_stationary_(FLAC__MetaData_SimpleIterator *iterator, const FLAC__StreamMetaData *block);
82 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, unsigned padding_length, FLAC__bool padding_is_last);
83 static FLAC__bool rewrite_whole_file_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool append);
84
85 static FLAC__bool chain_rewrite_chain_(FLAC__MetaData_Chain *chain);
86 static FLAC__bool chain_rewrite_file_(FLAC__MetaData_Chain *chain, const char *tempfile_path_prefix);
87
88 static void simple_iterator_push_(FLAC__MetaData_SimpleIterator *iterator);
89 static FLAC__bool simple_iterator_pop_(FLAC__MetaData_SimpleIterator *iterator);
90
91 /* return 0 if OK, 1 if read error, 2 if not a FLAC file */
92 static unsigned seek_to_first_metadata_block_(FILE *f);
93
94 static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append);
95 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);
96
97 static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__MetaData_SimpleIteratorStatus *status);
98 static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__MetaData_SimpleIteratorStatus *status);
99
100 static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status);
101 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status);
102 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename);
103
104 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats);
105 static void set_file_stats_(const char *filename, struct stat *stats);
106
107 static FLAC__MetaData_ChainStatus get_equivalent_status_(FLAC__MetaData_SimpleIteratorStatus status);
108
109
110 /****************************************************************************
111  *
112  * Level 0 implementation
113  *
114  ***************************************************************************/
115
116 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
117 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
118 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
119
120 FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetaData_StreamInfo *streaminfo)
121 {
122         FLAC__FileDecoder *decoder = FLAC__file_decoder_new();
123
124         if(0 == decoder)
125                 return false;
126
127         FLAC__file_decoder_set_md5_checking(decoder, false);
128         FLAC__file_decoder_set_filename(decoder, filename);
129         FLAC__file_decoder_set_write_callback(decoder, write_callback_);
130         FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
131         FLAC__file_decoder_set_error_callback(decoder, error_callback_);
132         FLAC__file_decoder_set_client_data(decoder, &streaminfo);
133
134         if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
135                 return false;
136
137         if(!FLAC__file_decoder_process_metadata(decoder))
138                 return false;
139
140         FLAC__file_decoder_finish(decoder);
141         FLAC__file_decoder_delete(decoder);
142
143         return 0 != streaminfo; /* the metadata_callback_() will set streaminfo to 0 on an error */
144 }
145
146 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
147 {
148         (void)decoder, (void)frame, (void)buffer, (void)client_data;
149
150         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
151 }
152
153 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
154 {
155         FLAC__StreamMetaData_StreamInfo **streaminfo = (FLAC__StreamMetaData_StreamInfo **)client_data;
156         (void)decoder;
157
158         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && 0 != *streaminfo)
159                 **streaminfo = metadata->data.stream_info;
160 }
161
162 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
163 {
164         FLAC__StreamMetaData_StreamInfo **streaminfo = (FLAC__StreamMetaData_StreamInfo **)client_data;
165         (void)decoder;
166
167         if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
168                 *streaminfo = 0;
169 }
170
171
172 /****************************************************************************
173  *
174  * Level 1 implementation
175  *
176  ***************************************************************************/
177
178 #define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4)
179 /* 1 for initial offset, +4 for our own personal use */
180
181 struct FLAC__MetaData_SimpleIterator {
182         FILE *file;
183         char *filename, *tempfile_path_prefix;
184         struct stat stats;
185         FLAC__bool has_stats;
186         FLAC__bool is_writable;
187         FLAC__MetaData_SimpleIteratorStatus status;
188         /*@@@ 2G limits here because of the offset type: */
189         long offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
190         long first_offset; /* this is the offset to the STREAMINFO block */
191         unsigned depth;
192         /* this is the metadata block header of the current block we are pointing to: */
193         FLAC__bool is_last;
194         FLAC__MetaDataType type;
195         unsigned length;
196 };
197
198 const char *FLAC__MetaData_SimpleIteratorStatusString[] = {
199         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK",
200         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT",
201         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE",
202         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE",
203         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE",
204         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA",
205         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR",
206         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR",
207         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR",
208         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR",
209         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR",
210         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR",
211         "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR"
212 };
213
214
215 FLAC__MetaData_SimpleIterator *FLAC__metadata_simple_iterator_new()
216 {
217         FLAC__MetaData_SimpleIterator *iterator = malloc(sizeof(FLAC__MetaData_SimpleIterator));
218
219         if(0 != iterator) {
220                 iterator->file = 0;
221                 iterator->filename = 0;
222                 iterator->tempfile_path_prefix = 0;
223                 iterator->has_stats = false;
224                 iterator->is_writable = false;
225                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
226                 iterator->first_offset = iterator->offset[0] = -1;
227                 iterator->depth = 0;
228         }
229
230         return iterator;
231 }
232
233 static void simple_iterator_free_guts_(FLAC__MetaData_SimpleIterator *iterator)
234 {
235         FLAC__ASSERT(0 != iterator);
236
237         if(0 != iterator->file) {
238                 fclose(iterator->file);
239                 iterator->file = 0;
240                 if(iterator->has_stats)
241                         set_file_stats_(iterator->filename, &iterator->stats);
242         }
243         if(0 != iterator->filename) {
244                 free(iterator->filename);
245                 iterator->filename = 0;
246         }
247         if(0 != iterator->tempfile_path_prefix) {
248                 free(iterator->tempfile_path_prefix);
249                 iterator->tempfile_path_prefix = 0;
250         }
251 }
252
253 void FLAC__metadata_simple_iterator_delete(FLAC__MetaData_SimpleIterator *iterator)
254 {
255         FLAC__ASSERT(0 != iterator);
256
257         simple_iterator_free_guts_(iterator);
258         free(iterator);
259 }
260
261 FLAC__MetaData_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__MetaData_SimpleIterator *iterator)
262 {
263         FLAC__MetaData_SimpleIteratorStatus status;
264
265         FLAC__ASSERT(0 != iterator);
266
267         status = iterator->status;
268         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
269         return status;
270 }
271
272 static FLAC__bool simple_iterator_prime_input_(FLAC__MetaData_SimpleIterator *iterator)
273 {
274         unsigned ret;
275
276         FLAC__ASSERT(0 != iterator);
277
278         iterator->is_writable = false;
279
280         if(0 == (iterator->file = fopen(iterator->filename, "r+b"))) {
281                 if(errno == EACCES) {
282                         if(0 == (iterator->file = fopen(iterator->filename, "rb"))) {
283                                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
284                                 return false;
285                         }
286                 }
287                 else {
288                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
289                         return false;
290                 }
291         }
292         else {
293                 iterator->is_writable = true;
294         }
295
296         ret = seek_to_first_metadata_block_(iterator->file);
297         switch(ret) {
298                 case 0:
299                         iterator->depth = 0;
300                         iterator->first_offset = iterator->offset[iterator->depth] = ftell(iterator->file);
301                         return read_metadata_block_header_(iterator);
302                 case 1:
303                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
304                         return false;
305                 case 2:
306                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE;
307                         return false;
308                 default:
309                         FLAC__ASSERT(0);
310                         return false;
311         }
312 }
313
314 #if 0
315 @@@ If we decide to finish implementing this, put this comment back in metadata.h
316 /*
317  * The 'tempfile_path_prefix' allows you to specify a directory where
318  * tempfiles should go.  Remember that if your metadata edits cause the
319  * FLAC file to grow, the entire file will have to be rewritten.  If
320  * 'tempfile_path_prefix' is NULL, the temp file will be written in the
321  * same directory as the original FLAC file.  This makes replacing the
322  * original with the tempfile fast but requires extra space in the same
323  * partition for the tempfile.  If space is a problem, you can pass a
324  * directory name belonging to a different partition in
325  * 'tempfile_path_prefix'.  Note that you should use the forward slash
326  * '/' as the directory separator.  A trailing slash is not needed; it
327  * will be added automatically.
328  */
329 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__MetaData_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix);
330 #endif
331
332 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__MetaData_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats)
333 {
334         const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */
335
336         FLAC__ASSERT(0 != iterator);
337         FLAC__ASSERT(0 != filename);
338
339         simple_iterator_free_guts_(iterator);
340
341         if(preserve_file_stats)
342                 iterator->has_stats = get_file_stats_(filename, &iterator->stats);
343
344         if(0 == (iterator->filename = strdup(filename))) {
345                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
346                 return false;
347         }
348         if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) {
349                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
350                 return false;
351         }
352
353         return simple_iterator_prime_input_(iterator);
354 }
355
356 FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__MetaData_SimpleIterator *iterator)
357 {
358         FLAC__ASSERT(0 != iterator);
359         FLAC__ASSERT(0 != iterator->file);
360
361         return iterator->is_writable;
362 }
363
364 FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__MetaData_SimpleIterator *iterator)
365 {
366         FLAC__ASSERT(0 != iterator);
367         FLAC__ASSERT(0 != iterator->file);
368
369         if(iterator->is_last)
370                 return false;
371
372         if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
373                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
374                 return false;
375         }
376
377         iterator->offset[iterator->depth] = ftell(iterator->file);
378
379         return read_metadata_block_header_(iterator);
380 }
381
382 FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__MetaData_SimpleIterator *iterator)
383 {
384         long this_offset;
385
386         FLAC__ASSERT(0 != iterator);
387         FLAC__ASSERT(0 != iterator->file);
388
389         if(iterator->offset[iterator->depth] == iterator->first_offset)
390                 return false;
391
392         if(0 != fseek(iterator->file, iterator->first_offset, SEEK_SET)) {
393                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
394                 return false;
395         }
396         this_offset = iterator->first_offset;
397         if(!read_metadata_block_header_(iterator))
398                 return false;
399
400         /* we ignore any error from ftell() and catch it in fseek() */
401         while(ftell(iterator->file) + (long)iterator->length < iterator->offset[iterator->depth]) {
402                 if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
403                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
404                         return false;
405                 }
406                 this_offset = ftell(iterator->file);
407                 if(!read_metadata_block_header_(iterator))
408                         return false;
409         }
410
411         iterator->offset[iterator->depth] = this_offset;
412
413         return true;
414 }
415
416 FLAC__MetaDataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__MetaData_SimpleIterator *iterator)
417 {
418         FLAC__ASSERT(0 != iterator);
419         FLAC__ASSERT(0 != iterator->file);
420
421         return iterator->type;
422 }
423
424 FLAC__StreamMetaData *FLAC__metadata_simple_iterator_get_block(FLAC__MetaData_SimpleIterator *iterator)
425 {
426         FLAC__StreamMetaData *block = FLAC__metadata_object_new(iterator->type);
427
428         FLAC__ASSERT(0 != iterator);
429         FLAC__ASSERT(0 != iterator->file);
430
431         if(0 != block) {
432                 block->is_last = iterator->is_last;
433                 block->length = iterator->length;
434
435                 if(!read_metadata_block_data_(iterator, block)) {
436                         FLAC__metadata_object_delete(block);
437                         return 0;
438                 }
439
440                 /* back up to the beginning of the block data to stay consistent */
441                 if(0 != fseek(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
442                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
443                         FLAC__metadata_object_delete(block);
444                         return 0;
445                 }
446         }
447         else
448                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
449
450         return block;
451 }
452
453 FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool use_padding)
454 {
455         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
456         FLAC__bool ret;
457
458         FLAC__ASSERT(0 != iterator);
459         FLAC__ASSERT(0 != iterator->file);
460
461         if(!iterator->is_writable) {
462                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE;
463                 return false;
464         }
465
466         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) {
467                 if(iterator->type != block->type) {
468                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
469                         return false;
470                 }
471         }
472
473         block->is_last = iterator->is_last;
474
475         if(iterator->length == block->length)
476                 return write_metadata_block_stationary_(iterator, block);
477         else if(iterator->length > block->length) {
478                 if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) {
479                         ret =  write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last);
480                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
481                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
482                         return ret;
483                 }
484                 else {
485                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
486                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
487                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
488                         return ret;
489                 }
490         }
491         else /* iterator->length < block->length */ {
492                 unsigned padding_leftover = 0;
493                 FLAC__bool padding_is_last = false;
494                 if(use_padding) {
495                         /* first see if we can even use padding */
496                         if(iterator->is_last) {
497                                 use_padding = false;
498                         }
499                         else {
500                                 const unsigned extra_padding_bytes_required = block->length - iterator->length;
501                                 simple_iterator_push_(iterator);
502                                 if(!FLAC__metadata_simple_iterator_next(iterator)) {
503                                         (void)simple_iterator_pop_(iterator);
504                                         return false;
505                                 }
506                                 if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
507                                         use_padding = false;
508                                 }
509                                 else {
510                                         if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) {
511                                                 padding_leftover = 0;
512                                                 block->is_last = iterator->is_last;
513                                         }
514                                         else if(iterator->length < extra_padding_bytes_required)
515                                                 use_padding = false;
516                                         else {
517                                                 padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required;
518                                                 padding_is_last = iterator->is_last;
519                                                 block->is_last = false;
520                                         }
521                                 }
522                                 if(!simple_iterator_pop_(iterator))
523                                         return false;
524                         }
525                 }
526                 if(use_padding) {
527                         if(padding_leftover == 0) {
528                                 ret = write_metadata_block_stationary_(iterator, block);
529                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
530                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
531                                 return ret;
532                         }
533                         else {
534                                 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
535                                 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
536                                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
537                                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
538                                 return ret;
539                         }
540                 }
541                 else {
542                         ret = rewrite_whole_file_(iterator, block, /*append=*/false);
543                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
544                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
545                         return ret;
546                 }
547         }
548 }
549
550 FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool use_padding)
551 {
552         unsigned padding_leftover = 0;
553         FLAC__bool padding_is_last = false;
554
555         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
556         FLAC__bool ret;
557
558         FLAC__ASSERT(0 != iterator);
559         FLAC__ASSERT(0 != iterator->file);
560
561         if(!iterator->is_writable)
562                 return false;
563
564         if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
565                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
566                 return false;
567         }
568
569         block->is_last = iterator->is_last;
570
571         if(use_padding) {
572                 /* first see if we can even use padding */
573                 if(iterator->is_last) {
574                         use_padding = false;
575                 }
576                 else {
577                         simple_iterator_push_(iterator);
578                         if(!FLAC__metadata_simple_iterator_next(iterator)) {
579                                 (void)simple_iterator_pop_(iterator);
580                                 return false;
581                         }
582                         if(iterator->type != FLAC__METADATA_TYPE_PADDING) {
583                                 use_padding = false;
584                         }
585                         else {
586                                 if(iterator->length == block->length) {
587                                         padding_leftover = 0;
588                                         block->is_last = iterator->is_last;
589                                 }
590                                 else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length)
591                                         use_padding = false;
592                                 else {
593                                         padding_leftover = iterator->length - block->length;
594                                         padding_is_last = iterator->is_last;
595                                         block->is_last = false;
596                                 }
597                         }
598                         if(!simple_iterator_pop_(iterator))
599                                 return false;
600                 }
601         }
602         if(use_padding) {
603                 /* move to the next block, which is suitable padding */
604                 if(!FLAC__metadata_simple_iterator_next(iterator))
605                         return false;
606                 if(padding_leftover == 0) {
607                         ret = write_metadata_block_stationary_(iterator, block);
608                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
609                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
610                         return ret;
611                 }
612                 else {
613                         FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
614                         ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
615                         FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
616                         FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
617                         return ret;
618                 }
619         }
620         else {
621                 ret = rewrite_whole_file_(iterator, block, /*append=*/true);
622                 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
623                 FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
624                 return ret;
625         }
626 }
627
628 FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__MetaData_SimpleIterator *iterator, FLAC__bool use_padding)
629 {
630         FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
631         FLAC__bool ret;
632
633         if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
634                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT;
635                 return false;
636         }
637
638         if(use_padding) {
639                 FLAC__StreamMetaData *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
640                 if(0 == padding) {
641                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
642                         return false;
643                 }
644                 padding->length = iterator->length;
645                 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) {
646                         FLAC__metadata_object_delete(padding);
647                         return false;
648                 }
649                 FLAC__metadata_object_delete(padding);
650                 if(!FLAC__metadata_simple_iterator_prev(iterator))
651                         return false;
652                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
653                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
654                 return true;
655         }
656         else {
657                 ret = rewrite_whole_file_(iterator, 0, /*append=*/false);
658                 FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
659                 FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
660                 return ret;
661         }
662 }
663
664
665
666 /****************************************************************************
667  *
668  * Level 2 implementation
669  *
670  ***************************************************************************/
671
672
673 typedef struct FLAC__MetaData_Node {
674         FLAC__StreamMetaData *data;
675         struct FLAC__MetaData_Node *prev, *next;
676 } FLAC__MetaData_Node;
677
678 struct FLAC__MetaData_Chain {
679         char *filename;
680         FLAC__MetaData_Node *head;
681         FLAC__MetaData_Node *tail;
682         unsigned nodes;
683         FLAC__MetaData_ChainStatus status;
684         long first_offset, last_offset; /*@@@ 2G limit */
685         /*
686          * This is the length of the chain initially read from the FLAC file.
687          * it is used to compare against the current_length to decide whether
688          * or not the whole file has to be rewritten.
689          */
690         unsigned initial_length; /*@@@ 4G limit */
691         unsigned current_length; /*@@@ 4G limit */
692 };
693
694 struct FLAC__MetaData_Iterator {
695         FLAC__MetaData_Chain *chain;
696         FLAC__MetaData_Node *current;
697 };
698
699 const char *FLAC__MetaData_ChainStatusString[] = {
700         "FLAC__METADATA_CHAIN_STATUS_OK",
701         "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT",
702         "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE",
703         "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE",
704         "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE",
705         "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA",
706         "FLAC__METADATA_CHAIN_STATUS_READ_ERROR",
707         "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR",
708         "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR",
709         "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
710         "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
711         "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
712         "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR"
713 };
714
715
716 static FLAC__MetaData_Node *node_new_()
717 {
718         FLAC__MetaData_Node *node = (FLAC__MetaData_Node*)malloc(sizeof(FLAC__MetaData_Node));
719         if(0 != node)
720                 memset(node, 0, sizeof(FLAC__MetaData_Node));
721         return node;
722 }
723
724 static void node_delete_(FLAC__MetaData_Node *node)
725 {
726         FLAC__ASSERT(0 != node);
727         if(0 != node->data)
728                 FLAC__metadata_object_delete(node->data);
729         free(node);
730 }
731
732 static void chain_append_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
733 {
734         FLAC__ASSERT(0 != chain);
735         FLAC__ASSERT(0 != node);
736         FLAC__ASSERT(0 != node->data);
737
738         node->next = node->prev = 0;
739         node->data->is_last = true;
740         if(0 != chain->tail)
741                 chain->tail->data->is_last = false;
742
743         if(0 == chain->head)
744                 chain->head = node;
745         else {
746                 FLAC__ASSERT(0 != chain->tail);
747                 chain->tail->next = node;
748                 node->prev = chain->tail;
749         }
750         chain->tail = node;
751         chain->nodes++;
752         chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
753 }
754
755 static void chain_remove_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
756 {
757         FLAC__ASSERT(0 != chain);
758         FLAC__ASSERT(0 != node);
759
760         if(node == chain->head)
761                 chain->head = node->next;
762         else
763                 node->prev->next = node->next;
764
765         if(node == chain->tail)
766                 chain->tail = node->prev;
767         else
768                 node->next->prev = node->prev;
769
770         if(0 != chain->tail)
771                 chain->tail->data->is_last = true;
772
773         chain->nodes--;
774         chain->current_length -= (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
775 }
776
777 static void chain_delete_node_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
778 {
779         chain_remove_node_(chain, node);
780         node_delete_(node);
781 }
782
783 static void iterator_insert_node_(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Node *node)
784 {
785         FLAC__ASSERT(0 != node);
786         FLAC__ASSERT(0 != node->data);
787         FLAC__ASSERT(0 != iterator);
788         FLAC__ASSERT(0 != iterator->current);
789         FLAC__ASSERT(0 != iterator->chain);
790         FLAC__ASSERT(0 != iterator->chain->head);
791         FLAC__ASSERT(0 != iterator->chain->tail);
792
793         node->data->is_last = false;
794
795         node->prev = iterator->current->prev;
796         node->next = iterator->current;
797
798         if(0 == node->prev)
799                 iterator->chain->head = node;
800         else
801                 node->prev->next = node;
802
803         iterator->current->prev = node;
804
805         iterator->chain->nodes++;
806         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
807 }
808
809 static void iterator_insert_node_after_(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Node *node)
810 {
811         FLAC__ASSERT(0 != node);
812         FLAC__ASSERT(0 != node->data);
813         FLAC__ASSERT(0 != iterator);
814         FLAC__ASSERT(0 != iterator->current);
815         FLAC__ASSERT(0 != iterator->chain);
816         FLAC__ASSERT(0 != iterator->chain->head);
817         FLAC__ASSERT(0 != iterator->chain->tail);
818
819         iterator->current->data->is_last = false;
820
821         node->prev = iterator->current;
822         node->next = iterator->current->next;
823
824         if(0 == node->next)
825                 iterator->chain->tail = node;
826         else
827                 node->next->prev = node;
828
829         node->prev->next = node;
830
831         iterator->chain->tail->data->is_last = true;
832
833         iterator->chain->nodes++;
834         iterator->chain->current_length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
835 }
836
837 /* return true iff node and node->next are both padding */
838 static FLAC__bool chain_merge_adjacent_padding_(FLAC__MetaData_Chain *chain, FLAC__MetaData_Node *node)
839 {
840         if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) {
841                 const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length;
842                 node->data->length += growth;
843                 chain->current_length += growth;
844
845                 chain_delete_node_(chain, node->next);
846                 return true;
847         }
848         else
849                 return false;
850 }
851
852 FLAC__MetaData_Chain *FLAC__metadata_chain_new()
853 {
854         FLAC__MetaData_Chain *chain = malloc(sizeof(FLAC__MetaData_Chain));
855
856         if(0 != chain) {
857                 chain->filename = 0;
858                 chain->head = chain->tail = 0;
859                 chain->nodes = 0;
860                 chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
861                 chain->initial_length = chain->current_length = 0;
862         }
863
864         return chain;
865 }
866
867 void FLAC__metadata_chain_delete(FLAC__MetaData_Chain *chain)
868 {
869         FLAC__MetaData_Node *node, *next;
870
871         FLAC__ASSERT(0 != chain);
872
873         for(node = chain->head; node; ) {
874                 next = node->next;
875                 node_delete_(node);
876                 node = next;
877         }
878
879         if(0 != chain->filename)
880                 free(chain->filename);
881
882         free(chain);
883 }
884
885 FLAC__MetaData_ChainStatus FLAC__metadata_chain_status(FLAC__MetaData_Chain *chain)
886 {
887         FLAC__MetaData_ChainStatus status;
888
889         FLAC__ASSERT(0 != chain);
890
891         status = chain->status;
892         chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
893         return status;
894 }
895
896 FLAC__bool FLAC__metadata_chain_read(FLAC__MetaData_Chain *chain, const char *filename)
897 {
898         FLAC__MetaData_SimpleIterator *iterator;
899         FLAC__MetaData_Node *node;
900
901         FLAC__ASSERT(0 != chain);
902         FLAC__ASSERT(0 != filename);
903
904         if(0 == (chain->filename = strdup(filename))) {
905                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
906                 return false;
907         }
908
909         if(0 == (iterator = FLAC__metadata_simple_iterator_new())) {
910                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
911                 return false;
912         }
913
914         if(!FLAC__metadata_simple_iterator_init(iterator, filename, /*preserve_file_stats=*/false)) {
915                 chain->status = get_equivalent_status_(iterator->status);
916                 return false;
917         }
918
919         chain->first_offset = iterator->offset[iterator->depth];
920
921         do {
922                 node = node_new_();
923                 if(0 == node) {
924                         chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
925                         return false;
926                 }
927                 node->data = FLAC__metadata_simple_iterator_get_block(iterator);
928                 if(0 == node->data) {
929                         node_delete_(node);
930                         chain->status = get_equivalent_status_(iterator->status);
931                         return false;
932                 }
933                 chain_append_node_(chain, node);
934         } while(FLAC__metadata_simple_iterator_next(iterator));
935
936         if(!iterator->is_last || iterator->status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) {
937                 chain->status = get_equivalent_status_(iterator->status);
938                 return false;
939         }
940
941         chain->last_offset = ftell(iterator->file) + iterator->length;
942         FLAC__metadata_simple_iterator_delete(iterator);
943
944         chain->initial_length = chain->current_length;
945         return true;
946 }
947
948 FLAC__bool FLAC__metadata_chain_write(FLAC__MetaData_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
949 {
950         struct stat stats;
951         const char *tempfile_path_prefix = 0;
952
953         if(use_padding) {
954                 if(chain->current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
955                         const unsigned delta = chain->initial_length - chain->current_length;
956                         chain->tail->data->length += delta;
957                         chain->current_length += delta;
958                         FLAC__ASSERT(chain->current_length == chain->initial_length);
959                 }
960                 else if(chain->current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
961                         FLAC__StreamMetaData *padding;
962                         FLAC__MetaData_Node *node;
963                         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
964                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
965                                 return false;
966                         }
967                         padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + chain->current_length);
968                         if(0 == (node = node_new_())) {
969                                 FLAC__metadata_object_delete(padding);
970                                 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
971                                 return false;
972                         }
973                         node->data = padding;
974                         chain_append_node_(chain, node);
975                         FLAC__ASSERT(chain->current_length == chain->initial_length);
976                 }
977                 else if(chain->current_length > chain->initial_length) {
978                         const unsigned delta = chain->current_length - chain->initial_length;
979                         if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
980                                 if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
981                                         chain_delete_node_(chain, chain->tail);
982                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
983                                 }
984                                 else if(chain->tail->data->length >= delta) {
985                                         chain->tail->data->length -= delta;
986                                         chain->current_length -= delta;
987                                         FLAC__ASSERT(chain->current_length == chain->initial_length);
988                                 }
989                         }
990                 }
991         }
992
993         if(preserve_file_stats)
994                 get_file_stats_(chain->filename, &stats);
995
996         if(chain->current_length == chain->initial_length) {
997                 if(!chain_rewrite_chain_(chain))
998                         return false;
999         }
1000         else {
1001                 if(!chain_rewrite_file_(chain, tempfile_path_prefix))
1002                         return false;
1003         }
1004
1005         if(preserve_file_stats)
1006                 set_file_stats_(chain->filename, &stats);
1007
1008         /* recompute lengths and offsets if necessary */
1009         if(chain->initial_length != chain->current_length) {
1010                 const FLAC__MetaData_Node *node;
1011                 chain->initial_length = chain->current_length;
1012                 chain->last_offset = chain->first_offset;
1013                 for(node = chain->head; node; node = node->next)
1014                         chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
1015         }
1016
1017         return true;
1018 }
1019
1020 void FLAC__metadata_chain_merge_padding(FLAC__MetaData_Chain *chain)
1021 {
1022         FLAC__MetaData_Node *node;
1023
1024         FLAC__ASSERT(0 != chain);
1025
1026         for(node = chain->head; node; ) {
1027                 if(!chain_merge_adjacent_padding_(chain, node))
1028                         node = node->next;
1029         }
1030 }
1031
1032 void FLAC__metadata_chain_sort_padding(FLAC__MetaData_Chain *chain)
1033 {
1034         FLAC__MetaData_Node *node, *save;
1035         unsigned i;
1036
1037         FLAC__ASSERT(0 != chain);
1038
1039         /*
1040          * Don't try and be too smart... this simple algo is good enough for
1041          * the small number of nodes that we deal with.
1042          */
1043         for(i = 0, node = chain->head; i < chain->nodes; i++) {
1044                 if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
1045                         save = node->next;
1046                         chain_remove_node_(chain, node);
1047                         chain_append_node_(chain, node);
1048                         node = save;
1049                 }
1050                 else {
1051                         node = node->next;
1052                 }
1053         }
1054
1055         FLAC__metadata_chain_merge_padding(chain);
1056 }
1057
1058
1059 FLAC__MetaData_Iterator *FLAC__metadata_iterator_new()
1060 {
1061         FLAC__MetaData_Iterator *iterator = malloc(sizeof(FLAC__MetaData_Iterator));
1062
1063         if(0 != iterator) {
1064                 iterator->current = 0;
1065                 iterator->chain = 0;
1066         }
1067
1068         return iterator;
1069 }
1070
1071 void FLAC__metadata_iterator_delete(FLAC__MetaData_Iterator *iterator)
1072 {
1073         FLAC__ASSERT(0 != iterator);
1074
1075         free(iterator);
1076 }
1077
1078 /*
1079  * Initialize the iterator to point to the first metadata block in the
1080  * given chain.
1081  */
1082 void FLAC__metadata_iterator_init(FLAC__MetaData_Iterator *iterator, FLAC__MetaData_Chain *chain)
1083 {
1084         FLAC__ASSERT(0 != iterator);
1085         FLAC__ASSERT(0 != chain);
1086         FLAC__ASSERT(0 != chain->head);
1087
1088         iterator->chain = chain;
1089         iterator->current = chain->head;
1090 }
1091
1092 FLAC__bool FLAC__metadata_iterator_next(FLAC__MetaData_Iterator *iterator)
1093 {
1094         FLAC__ASSERT(0 != iterator);
1095
1096         if(0 == iterator->current || 0 == iterator->current->next)
1097                 return false;
1098
1099         iterator->current = iterator->current->next;
1100         return true;
1101 }
1102
1103 FLAC__bool FLAC__metadata_iterator_prev(FLAC__MetaData_Iterator *iterator)
1104 {
1105         FLAC__ASSERT(0 != iterator);
1106
1107         if(0 == iterator->current || 0 == iterator->current->prev)
1108                 return false;
1109
1110         iterator->current = iterator->current->prev;
1111         return true;
1112 }
1113
1114 FLAC__MetaDataType FLAC__metadata_iterator_get_block_type(const FLAC__MetaData_Iterator *iterator)
1115 {
1116         FLAC__ASSERT(0 != iterator);
1117         FLAC__ASSERT(0 != iterator->current);
1118         FLAC__ASSERT(0 != iterator->current->data);
1119
1120         return iterator->current->data->type;
1121 }
1122
1123 FLAC__StreamMetaData *FLAC__metadata_iterator_get_block(FLAC__MetaData_Iterator *iterator)
1124 {
1125         FLAC__ASSERT(0 != iterator);
1126         FLAC__ASSERT(0 != iterator->current);
1127
1128         return iterator->current->data;
1129 }
1130
1131 FLAC__bool FLAC__metadata_iterator_set_block(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1132 {
1133         return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
1134 }
1135
1136 FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__MetaData_Iterator *iterator, FLAC__bool replace_with_padding)
1137 {
1138         FLAC__MetaData_Node *save;
1139
1140         FLAC__ASSERT(0 != iterator);
1141         FLAC__ASSERT(0 != iterator->current);
1142
1143         if(0 == iterator->current->prev) {
1144                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1145                 return false;
1146         }
1147
1148         save = iterator->current->prev;
1149
1150         if(replace_with_padding) {
1151                 FLAC__metadata_object_delete_data_(iterator->current->data);
1152                 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
1153         }
1154         else {
1155                 chain_delete_node_(iterator->chain, iterator->current);
1156         }
1157
1158         iterator->current = save;
1159         return true;
1160 }
1161
1162 FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1163 {
1164         FLAC__MetaData_Node *node;
1165
1166         FLAC__ASSERT(0 != iterator);
1167         FLAC__ASSERT(0 != iterator->current);
1168
1169         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1170                 return false;
1171
1172         if(0 == iterator->current->prev) {
1173                 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
1174                 return false;
1175         }
1176
1177         if(0 == (node = node_new_()))
1178                 return false;
1179
1180         node->data = block;
1181         iterator_insert_node_(iterator, node);
1182         iterator->current = node;
1183         return true;
1184 }
1185
1186 FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__MetaData_Iterator *iterator, FLAC__StreamMetaData *block)
1187 {
1188         FLAC__MetaData_Node *node;
1189
1190         FLAC__ASSERT(0 != iterator);
1191         FLAC__ASSERT(0 != iterator->current);
1192
1193         if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
1194                 return false;
1195
1196         if(0 == (node = node_new_()))
1197                 return false;
1198
1199         node->data = block;
1200         iterator_insert_node_after_(iterator, node);
1201         iterator->current = node;
1202         return true;
1203 }
1204
1205
1206 /****************************************************************************
1207  *
1208  * Metadata object routines
1209  *
1210  ***************************************************************************/
1211
1212 FLAC__StreamMetaData *FLAC__metadata_object_new(FLAC__MetaDataType type)
1213 {
1214         FLAC__StreamMetaData *object = malloc(sizeof(FLAC__StreamMetaData));
1215         if(0 != object) {
1216                 memset(object, 0, sizeof(FLAC__StreamMetaData));
1217                 object->is_last = false;
1218                 object->type = type;
1219                 switch(type) {
1220                         case FLAC__METADATA_TYPE_STREAMINFO:
1221                                 object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
1222                                 break;
1223                         case FLAC__METADATA_TYPE_PADDING:
1224                                 break;
1225                         case FLAC__METADATA_TYPE_APPLICATION:
1226                                 object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1227                                 break;
1228                         case FLAC__METADATA_TYPE_SEEKTABLE:
1229                                 break;
1230                         case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1231                                 object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN + FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
1232                                 break;
1233                         default:
1234                                 FLAC__ASSERT(0);
1235                 }
1236         }
1237
1238         return object;
1239 }
1240
1241 static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
1242 {
1243         if(bytes > 0 && 0 != from) {
1244                 if(0 == (*to = malloc(bytes)))
1245                         return false;
1246                 memcpy(*to, from, bytes);
1247         }
1248         else {
1249                 FLAC__ASSERT(0 == from);
1250                 FLAC__ASSERT(bytes == 0);
1251                 *to = 0;
1252         }
1253         return true;
1254 }
1255
1256 static FLAC__bool copy_vcentry_(FLAC__StreamMetaData_VorbisComment_Entry *to, const FLAC__StreamMetaData_VorbisComment_Entry *from)
1257 {
1258         to->length = from->length;
1259         if(0 == from->entry) {
1260                 FLAC__ASSERT(from->length == 0);
1261                 to->entry = 0;
1262         }
1263         else {
1264                 FLAC__ASSERT(from->length > 0);
1265                 if(0 == (to->entry = malloc(from->length)))
1266                         return false;
1267                 memcpy(to->entry, from->entry, from->length);
1268         }
1269         return true;
1270 }
1271
1272 FLAC__StreamMetaData *FLAC__metadata_object_copy(const FLAC__StreamMetaData *object)
1273 {
1274         FLAC__StreamMetaData *to;
1275         unsigned i;
1276
1277         FLAC__ASSERT(0 != object);
1278
1279         if(0 != (to = FLAC__metadata_object_new(object->type))) {
1280                 to->is_last = object->is_last;
1281                 to->type = object->type;
1282                 to->length = object->length;
1283                 switch(to->type) {
1284                         case FLAC__METADATA_TYPE_STREAMINFO:
1285                                 memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetaData_StreamInfo));
1286                                 break;
1287                         case FLAC__METADATA_TYPE_PADDING:
1288                                 break;
1289                         case FLAC__METADATA_TYPE_APPLICATION:
1290                                 memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8);
1291                                 if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) {
1292                                         FLAC__metadata_object_delete(to);
1293                                         return 0;
1294                                 }
1295                                 break;
1296                         case FLAC__METADATA_TYPE_SEEKTABLE:
1297                                 to->data.seek_table.num_points = object->data.seek_table.num_points;
1298                                 if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetaData_SeekPoint))) {
1299                                         FLAC__metadata_object_delete(to);
1300                                         return 0;
1301                                 }
1302                                 break;
1303                         case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1304                                 if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) {
1305                                         FLAC__metadata_object_delete(to);
1306                                         return 0;
1307                                 }
1308                                 to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
1309                                 if(object->data.vorbis_comment.num_comments == 0) {
1310                                         FLAC__ASSERT(0 == object->data.vorbis_comment.comments);
1311                                         to->data.vorbis_comment.comments = 0;
1312                                 }
1313                                 else {
1314                                         FLAC__ASSERT(0 != object->data.vorbis_comment.comments);
1315                                         if(0 == (to->data.vorbis_comment.comments = malloc(object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry*)))) {
1316                                                 FLAC__metadata_object_delete(to);
1317                                                 return 0;
1318                                         }
1319                                 }
1320                                 /* Need to do this to set the pointers inside the comments to 0.
1321                                  * In case of an error in the following loop, the object will be
1322                                  * deleted and we don't want the destructor freeing uninitialized
1323                                  * pointers.
1324                                  */
1325                                 if(0 != to->data.vorbis_comment.comments)
1326                                         memset(to->data.vorbis_comment.comments, 0, object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry*));
1327                                 for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
1328                                         if(!copy_vcentry_(to->data.vorbis_comment.comments+i, object->data.vorbis_comment.comments+i)) {
1329                                                 FLAC__metadata_object_delete(to);
1330                                                 return 0;
1331                                         }
1332                                 }
1333                                 break;
1334                         default:
1335                                 FLAC__ASSERT(0);
1336                 }
1337         }
1338
1339         return to;
1340 }
1341
1342 void FLAC__metadata_object_delete_data_(FLAC__StreamMetaData *object)
1343 {
1344         unsigned i;
1345
1346         FLAC__ASSERT(0 != object);
1347
1348         switch(object->type) {
1349                 case FLAC__METADATA_TYPE_STREAMINFO:
1350                 case FLAC__METADATA_TYPE_PADDING:
1351                         break;
1352                 case FLAC__METADATA_TYPE_APPLICATION:
1353                         if(0 != object->data.application.data)
1354                                 free(object->data.application.data);
1355                         break;
1356                 case FLAC__METADATA_TYPE_SEEKTABLE:
1357                         if(0 != object->data.seek_table.points)
1358                                 free(object->data.seek_table.points);
1359                         break;
1360                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1361                         if(0 != object->data.vorbis_comment.vendor_string.entry)
1362                                 free(object->data.vorbis_comment.vendor_string.entry);
1363                         for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
1364                                 if(0 != object->data.vorbis_comment.comments[i].entry)
1365                                         free(object->data.vorbis_comment.comments[i].entry);
1366                         }
1367                         if(0 != object->data.vorbis_comment.comments)
1368                                 free(object->data.vorbis_comment.comments);
1369                         break;
1370                 default:
1371                         FLAC__ASSERT(0);
1372         }
1373 }
1374
1375 void FLAC__metadata_object_delete(FLAC__StreamMetaData *object)
1376 {
1377         FLAC__metadata_object_delete_data_(object);
1378         free(object);
1379 }
1380
1381 FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetaData *object, FLAC__byte *data, unsigned length, FLAC__bool copy)
1382 {
1383         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION);
1384         FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
1385
1386         if(0 != object->data.application.data)
1387                 free(object->data.application.data);
1388
1389         if(copy) {
1390                 if(!copy_bytes_(&object->data.application.data, data, length))
1391                         return false;
1392         }
1393         else {
1394                 object->data.application.data = data;
1395         }
1396         object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8 + length;
1397         return true;
1398 }
1399
1400 FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_new(unsigned num_points)
1401 {
1402         FLAC__StreamMetaData_SeekPoint *object_array;
1403
1404         FLAC__ASSERT(num_points > 0);
1405
1406         object_array = malloc(num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1407
1408         if(0 != object_array)
1409                 memset(object_array, 0, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1410
1411         return object_array;
1412 }
1413
1414 FLAC__StreamMetaData_SeekPoint *FLAC__metadata_object_seekpoint_array_copy(const FLAC__StreamMetaData_SeekPoint *object_array, unsigned num_points)
1415 {
1416         FLAC__StreamMetaData_SeekPoint *return_array;
1417
1418         FLAC__ASSERT(0 != object_array);
1419         FLAC__ASSERT(num_points > 0);
1420
1421         return_array = FLAC__metadata_object_seekpoint_array_new(num_points);
1422
1423         if(0 != return_array)
1424                 memcpy(return_array, object_array, num_points * sizeof(FLAC__StreamMetaData_SeekPoint));
1425
1426         return return_array;
1427 }
1428
1429 void FLAC__metadata_object_seekpoint_array_delete(FLAC__StreamMetaData_SeekPoint *object_array)
1430 {
1431         FLAC__ASSERT(0 != object_array);
1432
1433         free(object_array);
1434 }
1435
1436 FLAC__bool FLAC__metadata_object_seekpoint_array_resize(FLAC__StreamMetaData_SeekPoint **object_array, unsigned old_num_points, unsigned new_num_points)
1437 {
1438         FLAC__ASSERT(0 != object_array);
1439
1440         if(0 == *object_array) {
1441                 FLAC__ASSERT(old_num_points == 0);
1442                 if(0 == new_num_points)
1443                         return true;
1444                 else
1445                         return 0 != (*object_array = FLAC__metadata_object_seekpoint_array_new(new_num_points));
1446         }
1447         else {
1448                 const unsigned old_size = old_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
1449                 const unsigned new_size = new_num_points * sizeof(FLAC__StreamMetaData_SeekPoint);
1450
1451                 FLAC__ASSERT(old_num_points > 0);
1452
1453                 if(new_size == 0) {
1454                         free(*object_array);
1455                         *object_array = 0;
1456                 }
1457                 else if(0 == (*object_array = realloc(*object_array, new_size)))
1458                         return false;
1459
1460                 if(new_size > old_size)
1461                         memset(*object_array + old_num_points, 0, new_size - old_size);
1462
1463                 return true;
1464         }
1465 }
1466
1467 FLAC__bool FLAC__metadata_object_seektable_set_points(FLAC__StreamMetaData *object, FLAC__StreamMetaData_SeekPoint *points, unsigned num_points, FLAC__bool copy)
1468 {
1469         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
1470         FLAC__ASSERT((0 != points && num_points > 0) || (0 == points && num_points == 0 && copy == false));
1471
1472         object->data.seek_table.num_points = num_points;
1473
1474         if(0 != object->data.seek_table.points)
1475                 FLAC__metadata_object_seekpoint_array_delete(object->data.seek_table.points);
1476
1477         if(copy) {
1478                 if(0 == (object->data.seek_table.points = FLAC__metadata_object_seekpoint_array_copy(points, num_points)))
1479                         return false;
1480         }
1481         else {
1482                 object->data.seek_table.points = points;
1483         }
1484         object->length = num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1485         return true;
1486 }
1487
1488 FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_vorbiscomment_entry_array_new(unsigned num_comments)
1489 {
1490         FLAC__StreamMetaData_VorbisComment_Entry *object_array;
1491
1492         FLAC__ASSERT(num_comments > 0);
1493
1494         object_array = malloc(num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
1495
1496         if(0 != object_array)
1497                 memset(object_array, 0, num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry));
1498
1499         return object_array;
1500 }
1501
1502 FLAC__StreamMetaData_VorbisComment_Entry *FLAC__metadata_object_vorbiscomment_entry_array_copy(const FLAC__StreamMetaData_VorbisComment_Entry *object_array, unsigned num_comments)
1503 {
1504         FLAC__StreamMetaData_VorbisComment_Entry *return_array;
1505
1506         FLAC__ASSERT(0 != object_array);
1507         FLAC__ASSERT(num_comments > 0);
1508
1509         return_array = FLAC__metadata_object_vorbiscomment_entry_array_new(num_comments);
1510
1511         if(0 != return_array) {
1512                 unsigned i;
1513                 for(i = 0; i < num_comments; i++) {
1514                         return_array[i].length = object_array[i].length;
1515                         if(object_array[i].length == 0)
1516                                 return_array[i].entry = 0;
1517                         else if(!copy_bytes_(&(return_array[i].entry), object_array[i].entry, object_array[i].length)) {
1518                                 FLAC__metadata_object_vorbiscomment_entry_array_delete(return_array, num_comments);
1519                                 return 0;
1520                         }
1521                 }
1522         }
1523
1524         return return_array;
1525 }
1526
1527 void FLAC__metadata_object_vorbiscomment_entry_array_delete(FLAC__StreamMetaData_VorbisComment_Entry *object_array, unsigned num_comments)
1528 {
1529         unsigned i;
1530
1531         FLAC__ASSERT(0 != object_array && num_comments > 0);
1532
1533         for(i = 0; i < num_comments; i++)
1534                 if(0 != object_array[i].entry)
1535                         free(object_array[i].entry);
1536
1537         if(0 != object_array)
1538                 free(object_array);
1539 }
1540
1541 FLAC__bool FLAC__metadata_object_vorbiscomment_entry_array_resize(FLAC__StreamMetaData_VorbisComment_Entry **object_array, unsigned old_num_comments, unsigned new_num_comments)
1542 {
1543         FLAC__ASSERT(0 != object_array);
1544
1545         if(0 == *object_array) {
1546                 FLAC__ASSERT(old_num_comments == 0);
1547                 if(0 == new_num_comments)
1548                         return true;
1549                 else
1550                         return 0 != (*object_array = FLAC__metadata_object_vorbiscomment_entry_array_new(new_num_comments));
1551         }
1552         else {
1553                 const unsigned old_size = old_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
1554                 const unsigned new_size = new_num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry);
1555
1556                 FLAC__ASSERT(old_num_comments > 0);
1557
1558                 /* if shrinking, free the truncated entries */
1559                 if(new_num_comments < old_num_comments) {
1560                         unsigned i;
1561                         for(i = new_num_comments; i < old_num_comments; i++)
1562                                 if(0 != (*object_array)[i].entry)
1563                                         free((*object_array)[i].entry);
1564                 }
1565
1566                 if(new_size == 0) {
1567                         free(*object_array);
1568                         *object_array = 0;
1569                 }
1570                 else if(0 == (*object_array = realloc(*object_array, new_size)))
1571                         return false;
1572
1573                 /* if growing, zero all the length/pointers of new elements */
1574                 if(new_size > old_size)
1575                         memset(*object_array + old_num_comments, 0, new_size - old_size);
1576
1577                 return true;
1578         }
1579 }
1580
1581 FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetaData *object, FLAC__byte *entry, unsigned length, FLAC__bool copy)
1582 {
1583         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
1584         FLAC__ASSERT((0 != entry && length > 0) || (0 == entry && length == 0 && copy == false));
1585
1586         if(0 != object->data.vorbis_comment.vendor_string.entry)
1587                 free(object->data.vorbis_comment.vendor_string.entry);
1588
1589         object->length -= object->data.vorbis_comment.vendor_string.length;
1590
1591         if(copy) {
1592                 if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, entry, length)) {
1593                         object->data.vorbis_comment.vendor_string.length = 0;
1594                         return false;
1595                 }
1596         }
1597         else {
1598                 object->data.vorbis_comment.vendor_string.entry = entry;
1599         }
1600
1601         object->data.vorbis_comment.vendor_string.length = length;
1602         object->length += object->data.vorbis_comment.vendor_string.length;
1603
1604         return true;
1605 }
1606
1607 FLAC__bool FLAC__metadata_object_vorbiscomment_set_comments(FLAC__StreamMetaData *object, FLAC__StreamMetaData_VorbisComment_Entry *comments, unsigned num_comments, FLAC__bool copy)
1608 {
1609         unsigned i;
1610
1611         FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
1612         FLAC__ASSERT((0 != comments && num_comments > 0) || (0 == comments && num_comments == 0 && copy == false));
1613
1614         object->data.vorbis_comment.num_comments = num_comments;
1615
1616         if(0 != object->data.vorbis_comment.comments)
1617                 FLAC__metadata_object_vorbiscomment_entry_array_delete(object->data.vorbis_comment.comments, num_comments);
1618
1619         if(copy) {
1620                 if(0 == (object->data.vorbis_comment.comments = FLAC__metadata_object_vorbiscomment_entry_array_copy(comments, num_comments)))
1621                         return false;
1622         }
1623         else {
1624                 object->data.vorbis_comment.comments = comments;
1625         }
1626         object->length = num_comments * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1627
1628         /* calculate the new length */
1629         object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN) / 8;
1630         object->length += object->data.vorbis_comment.vendor_string.length;
1631         object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8;
1632         for(i = 0; i < object->data.vorbis_comment.num_comments; i++) {
1633                 object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8);
1634                 object->length += object->data.vorbis_comment.comments[i].length;
1635         }
1636
1637         return true;
1638 }
1639
1640
1641 /****************************************************************************
1642  *
1643  * Local function definitions
1644  *
1645  ***************************************************************************/
1646
1647 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1648 {
1649         unsigned i;
1650
1651         b += bytes;
1652
1653         for(i = 0; i < bytes; i++) {
1654                 *(--b) = (FLAC__byte)(val & 0xff);
1655                 val >>= 8;
1656         }
1657 }
1658
1659 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
1660 {
1661         unsigned i;
1662
1663         for(i = 0; i < bytes; i++) {
1664                 *(b++) = (FLAC__byte)(val & 0xff);
1665                 val >>= 8;
1666         }
1667 }
1668
1669 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes)
1670 {
1671         unsigned i;
1672
1673         b += bytes;
1674
1675         for(i = 0; i < bytes; i++) {
1676                 *(--b) = (FLAC__byte)(val & 0xff);
1677                 val >>= 8;
1678         }
1679 }
1680
1681 FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes)
1682 {
1683         FLAC__uint32 ret = 0;
1684         unsigned i;
1685
1686         for(i = 0; i < bytes; i++)
1687                 ret = (ret << 8) | (FLAC__uint32)(*b++);
1688
1689         return ret;
1690 }
1691
1692 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes)
1693 {
1694         FLAC__uint32 ret = 0;
1695         unsigned i;
1696
1697         b += bytes;
1698
1699         for(i = 0; i < bytes; i++)
1700                 ret = (ret << 8) | (FLAC__uint32)(*--b);
1701
1702         return ret;
1703 }
1704
1705 FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes)
1706 {
1707         FLAC__uint64 ret = 0;
1708         unsigned i;
1709
1710         for(i = 0; i < bytes; i++)
1711                 ret = (ret << 8) | (FLAC__uint64)(*b++);
1712
1713         return ret;
1714 }
1715
1716 FLAC__bool read_metadata_block_header_(FLAC__MetaData_SimpleIterator *iterator)
1717 {
1718         FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
1719
1720         FLAC__ASSERT(0 != iterator);
1721         FLAC__ASSERT(0 != iterator->file);
1722
1723         if(fread(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, iterator->file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1724                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1725                 return false;
1726         }
1727
1728         iterator->is_last = raw_header[0] & 0x80? true : false;
1729         iterator->type = (FLAC__MetaDataType)(raw_header[0] & 0x7f);
1730         iterator->length = unpack_uint32_(raw_header + 1, 3);
1731
1732         /* do some checking */
1733         if(iterator->type > FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1734                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
1735                 return false;
1736         }
1737
1738         return true;
1739 }
1740
1741 FLAC__bool read_metadata_block_data_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block)
1742 {
1743         FLAC__ASSERT(0 != iterator);
1744         FLAC__ASSERT(0 != iterator->file);
1745
1746         switch(block->type) {
1747                 case FLAC__METADATA_TYPE_STREAMINFO:
1748                         iterator->status = read_metadata_block_data_streaminfo_(iterator->file, &block->data.stream_info);
1749                         break;
1750                 case FLAC__METADATA_TYPE_PADDING:
1751                         iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length);
1752                         break;
1753                 case FLAC__METADATA_TYPE_APPLICATION:
1754                         iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length);
1755                         break;
1756                 case FLAC__METADATA_TYPE_SEEKTABLE:
1757                         iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length);
1758                         break;
1759                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1760                         iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment);
1761                         break;
1762                 default:
1763                         FLAC__ASSERT(0);
1764                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1765         }
1766
1767         return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1768 }
1769
1770 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetaData_StreamInfo *block)
1771 {
1772         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
1773
1774         FLAC__ASSERT(0 != file);
1775
1776         if(fread(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1777                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1778
1779         b = buffer;
1780
1781         /* @@@ we are using hardcoded numbers for simplicity but we should
1782          * probably eventually write a bit-level unpacker and use the
1783          * _STREAMINFO_ constants.
1784          */
1785         block->min_blocksize = unpack_uint32_(b, 2); b += 2;
1786         block->max_blocksize = unpack_uint32_(b, 2); b += 2;
1787         block->min_framesize = unpack_uint32_(b, 3); b += 3;
1788         block->max_framesize = unpack_uint32_(b, 3); b += 3;
1789         block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
1790         block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
1791         block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 1) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
1792         block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
1793         memcpy(block->md5sum, b+8, 16);
1794
1795         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1796 }
1797
1798
1799 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetaData_Padding *block, unsigned block_length)
1800 {
1801         FLAC__ASSERT(0 != file);
1802
1803         (void)block; /* nothing to do; we don't care about reading the padding bytes */
1804
1805         if(0 != fseek(file, block_length, SEEK_CUR))
1806                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
1807
1808         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1809 }
1810
1811 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetaData_Application *block, unsigned block_length)
1812 {
1813         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
1814
1815         FLAC__ASSERT(0 != file);
1816
1817         if(fread(block->id, 1, id_bytes, file) != id_bytes)
1818                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1819
1820         block_length -= id_bytes;
1821
1822         if(block_length == 0) {
1823                 block->data = 0;
1824         }
1825         else {
1826                 if(0 == (block->data = malloc(block_length)))
1827                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1828
1829                 if(fread(block->data, 1, block_length, file) != block_length)
1830                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1831         }
1832
1833         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1834 }
1835
1836 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetaData_SeekTable *block, unsigned block_length)
1837 {
1838         unsigned i;
1839         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
1840
1841         FLAC__ASSERT(0 != file);
1842         FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0);
1843
1844         block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
1845
1846         if(block->num_points == 0)
1847                 block->points = 0;
1848         else if(0 == (block->points = malloc(block->num_points * sizeof(FLAC__StreamMetaData_SeekPoint))))
1849                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1850
1851         for(i = 0; i < block->num_points; i++) {
1852                 if(fread(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
1853                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1854                 /*@@@ some MAGIC NUMBERs here */
1855                 block->points[i].sample_number = unpack_uint64_(buffer, 8);
1856                 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
1857                 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
1858         }
1859
1860         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1861 }
1862
1863 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetaData_VorbisComment_Entry *entry)
1864 {
1865         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1866         FLAC__byte buffer[FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8];
1867
1868         FLAC__ASSERT(0 != file);
1869
1870         if(fread(buffer, 1, entry_length_len, file) != entry_length_len)
1871                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1872         entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
1873
1874         if(entry->length == 0) {
1875                 entry->entry = 0;
1876         }
1877         else {
1878                 if(0 == (entry->entry = malloc(entry->length)))
1879                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1880
1881                 if(fread(entry->entry, 1, entry->length, file) != entry->length)
1882                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1883         }
1884
1885         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1886 }
1887
1888 FLAC__MetaData_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetaData_VorbisComment *block)
1889 {
1890         unsigned i;
1891         FLAC__MetaData_SimpleIteratorStatus status;
1892         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
1893         FLAC__byte buffer[FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8];
1894
1895         FLAC__ASSERT(0 != file);
1896
1897         if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, &(block->vendor_string))))
1898                 return status;
1899
1900         if(fread(buffer, 1, num_comments_len, file) != num_comments_len)
1901                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
1902         block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
1903
1904         if(block->num_comments == 0) {
1905                 block->comments = 0;
1906         }
1907         else if(0 == (block->comments = malloc(block->num_comments * sizeof(FLAC__StreamMetaData_VorbisComment_Entry))))
1908                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
1909
1910         for(i = 0; i < block->num_comments; i++) {
1911                 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, block->comments + i)))
1912                         return status;
1913         }
1914
1915         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1916 }
1917
1918 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block)
1919 {
1920         FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
1921
1922         FLAC__ASSERT(0 != file);
1923         FLAC__ASSERT(0 != status);
1924         FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
1925
1926         buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type;
1927         pack_uint32_(block->length, buffer + 1, 3);
1928
1929         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, file) != FLAC__STREAM_METADATA_HEADER_LENGTH) {
1930                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1931                 return false;
1932         }
1933
1934         return true;
1935 }
1936
1937 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__MetaData_SimpleIteratorStatus *status, const FLAC__StreamMetaData *block)
1938 {
1939         FLAC__ASSERT(0 != file);
1940         FLAC__ASSERT(0 != status);
1941
1942         switch(block->type) {
1943                 case FLAC__METADATA_TYPE_STREAMINFO:
1944                         *status = write_metadata_block_data_streaminfo_(file, &block->data.stream_info);
1945                         break;
1946                 case FLAC__METADATA_TYPE_PADDING:
1947                         *status = write_metadata_block_data_padding_(file, &block->data.padding, block->length);
1948                         break;
1949                 case FLAC__METADATA_TYPE_APPLICATION:
1950                         *status = write_metadata_block_data_application_(file, &block->data.application, block->length);
1951                         break;
1952                 case FLAC__METADATA_TYPE_SEEKTABLE:
1953                         *status = write_metadata_block_data_seektable_(file, &block->data.seek_table);
1954                         break;
1955                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
1956                         *status = write_metadata_block_data_vorbis_comment_(file, &block->data.vorbis_comment);
1957                         break;
1958                 default:
1959                         FLAC__ASSERT(0);
1960                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
1961         }
1962         return (*status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
1963 }
1964
1965 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_streaminfo_(FILE *file, const FLAC__StreamMetaData_StreamInfo *block)
1966 {
1967         FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
1968         const unsigned channels1 = block->channels - 1;
1969         const unsigned bps1 = block->bits_per_sample - 1;
1970
1971         FLAC__ASSERT(0 != file);
1972
1973         /* @@@ we are using hardcoded numbers for simplicity but we should
1974          * probably eventually write a bit-level packer and use the
1975          * _STREAMINFO_ constants.
1976          */
1977         pack_uint32_(block->min_blocksize, buffer, 2);
1978         pack_uint32_(block->max_blocksize, buffer+2, 2);
1979         pack_uint32_(block->min_framesize, buffer+4, 3);
1980         pack_uint32_(block->max_framesize, buffer+7, 3);
1981         buffer[10] = (block->sample_rate >> 12) & 0xff;
1982         buffer[11] = (block->sample_rate >> 4) & 0xff;
1983         buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4);
1984         buffer[13] = ((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f);
1985         pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4);
1986         memcpy(buffer+18, block->md5sum, 16);
1987
1988         if(fwrite(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
1989                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
1990
1991         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1992 }
1993
1994 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_padding_(FILE *file, const FLAC__StreamMetaData_Padding *block, unsigned block_length)
1995 {
1996         unsigned i, n = block_length;
1997         FLAC__byte buffer[1024];
1998
1999         FLAC__ASSERT(0 != file);
2000
2001         (void)block;
2002
2003         memset(buffer, 0, 1024);
2004
2005         for(i = 0; i < n/1024; i++)
2006                 if(fwrite(buffer, 1, 1024, file) != 1024)
2007                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2008
2009         n %= 1024;
2010         
2011         if(fwrite(buffer, 1, n, file) != n)
2012                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2013
2014         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2015 }
2016
2017 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_application_(FILE *file, const FLAC__StreamMetaData_Application *block, unsigned block_length)
2018 {
2019         const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
2020
2021         FLAC__ASSERT(0 != file);
2022
2023         if(fwrite(block->id, 1, id_bytes, file) != id_bytes)
2024                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2025
2026         block_length -= id_bytes;
2027
2028         if(fwrite(block->data, 1, block_length, file) != block_length)
2029                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2030
2031         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2032 }
2033
2034 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetaData_SeekTable *block)
2035 {
2036         unsigned i;
2037         FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
2038
2039         FLAC__ASSERT(0 != file);
2040
2041         for(i = 0; i < block->num_points; i++) {
2042                 /*@@@ some MAGIC NUMBERs here */
2043                 pack_uint64_(block->points[i].sample_number, buffer, 8);
2044                 pack_uint64_(block->points[i].stream_offset, buffer+8, 8);
2045                 pack_uint32_(block->points[i].frame_samples, buffer+16, 2);
2046                 if(fwrite(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
2047                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2048         }
2049
2050         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2051 }
2052
2053 FLAC__MetaData_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetaData_VorbisComment *block)
2054 {
2055         unsigned i;
2056         const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
2057         const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2058         FLAC__byte buffer[max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8];
2059
2060         FLAC__ASSERT(0 != file);
2061
2062         pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
2063         if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
2064                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2065         if(fwrite(block->vendor_string.entry, 1, block->vendor_string.length, file) != block->vendor_string.length)
2066                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2067
2068         pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len);
2069         if(fwrite(buffer, 1, num_comments_len, file) != num_comments_len)
2070                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2071
2072         for(i = 0; i < block->num_comments; i++) {
2073                 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len);
2074                 if(fwrite(buffer, 1, entry_length_len, file) != entry_length_len)
2075                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2076                 if(fwrite(block->comments[i].entry, 1, block->comments[i].length, file) != block->comments[i].length)
2077                         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2078         }
2079
2080         return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2081 }
2082
2083 FLAC__bool write_metadata_block_stationary_(FLAC__MetaData_SimpleIterator *iterator, const FLAC__StreamMetaData *block)
2084 {
2085         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2086                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2087                 return false;
2088         }
2089
2090         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
2091                 return false;
2092
2093         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
2094                 return false;
2095
2096         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2097                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2098                 return false;
2099         }
2100
2101         return read_metadata_block_header_(iterator);
2102 }
2103
2104 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, unsigned padding_length, FLAC__bool padding_is_last)
2105 {
2106         FLAC__StreamMetaData *padding;
2107
2108         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2109                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2110                 return false;
2111         }
2112
2113         block->is_last = false;
2114
2115         if(!write_metadata_block_header_(iterator->file, &iterator->status, block))
2116                 return false;
2117
2118         if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
2119                 return false;
2120
2121         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
2122                 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2123
2124         padding->is_last = padding_is_last;
2125         padding->length = padding_length;
2126
2127         if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) {
2128                 FLAC__metadata_object_delete(padding);
2129                 return false;
2130         }
2131
2132         if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) {
2133                 FLAC__metadata_object_delete(padding);
2134                 return false;
2135         }
2136
2137         FLAC__metadata_object_delete(padding);
2138
2139         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2140                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2141                 return false;
2142         }
2143
2144         return read_metadata_block_header_(iterator);
2145 }
2146
2147 FLAC__bool rewrite_whole_file_(FLAC__MetaData_SimpleIterator *iterator, FLAC__StreamMetaData *block, FLAC__bool append)
2148 {
2149         FILE *tempfile;
2150         char *tempfilename;
2151         int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
2152         long fixup_is_last_flag_offset = -1;
2153
2154         FLAC__ASSERT(0 != block || append == false);
2155
2156         if(iterator->is_last) {
2157                 if(append) {
2158                         fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */
2159                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
2160                 }
2161                 else if(0 == block) {
2162                         simple_iterator_push_(iterator);
2163                         if(!FLAC__metadata_simple_iterator_prev(iterator)) {
2164                                 (void)simple_iterator_pop_(iterator);
2165                                 return false;
2166                         }
2167                         fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */
2168                         fixup_is_last_flag_offset = iterator->offset[iterator->depth];
2169                         if(!simple_iterator_pop_(iterator))
2170                                 return false;
2171                 }
2172         }
2173
2174         if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append))
2175                 return false;
2176
2177         if(0 != block) {
2178                 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) {
2179                         cleanup_tempfile_(&tempfile, &tempfilename);
2180                         return false;
2181                 }
2182
2183                 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) {
2184                         cleanup_tempfile_(&tempfile, &tempfilename);
2185                         return false;
2186                 }
2187         }
2188
2189         if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0))
2190                 return false;
2191
2192         if(append)
2193                 return FLAC__metadata_simple_iterator_next(iterator);
2194
2195         return true;
2196 }
2197
2198 FLAC__bool chain_rewrite_chain_(FLAC__MetaData_Chain *chain)
2199 {
2200         FILE *f;
2201         FLAC__MetaData_Node *node;
2202         FLAC__MetaData_SimpleIteratorStatus status;
2203
2204         FLAC__ASSERT(0 != chain);
2205         FLAC__ASSERT(0 != chain->filename);
2206         FLAC__ASSERT(0 != chain->head);
2207
2208         if(0 == (f = fopen(chain->filename, "r+b"))) {
2209                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2210                 return false;
2211         }
2212         if(0 != fseek(f, chain->first_offset, SEEK_SET)) {
2213                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2214                 return false;
2215         }
2216
2217         for(node = chain->head; node; node = node->next) {
2218                 if(!write_metadata_block_header_(f, &status, node->data)) {
2219                         chain->status = get_equivalent_status_(status);
2220                         return false;
2221                 }
2222                 if(!write_metadata_block_data_(f, &status, node->data)) {
2223                         chain->status = get_equivalent_status_(status);
2224                         return false;
2225                 }
2226         }
2227
2228         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
2229
2230         (void)fclose(f);
2231
2232         return true;
2233 }
2234
2235 FLAC__bool chain_rewrite_file_(FLAC__MetaData_Chain *chain, const char *tempfile_path_prefix)
2236 {
2237         FILE *f, *tempfile;
2238         char *tempfilename;
2239         FLAC__MetaData_SimpleIteratorStatus status;
2240         const FLAC__MetaData_Node *node;
2241
2242         FLAC__ASSERT(0 != chain);
2243         FLAC__ASSERT(0 != chain->filename);
2244         FLAC__ASSERT(0 != chain->head);
2245
2246         /* copy the file prefix (data up to first metadata block */
2247         if(0 == (f = fopen(chain->filename, "rb"))) {
2248                 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2249                 return false;
2250         }
2251         if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) {
2252                 chain->status = get_equivalent_status_(status);
2253                 cleanup_tempfile_(&tempfile, &tempfilename);
2254                 return false;
2255         }
2256         if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) {
2257                 chain->status = get_equivalent_status_(status);
2258                 cleanup_tempfile_(&tempfile, &tempfilename);
2259                 return false;
2260         }
2261
2262         /* write the metadata */
2263         for(node = chain->head; node; node = node->next) {
2264                 if(!write_metadata_block_header_(tempfile, &status, node->data)) {
2265                         chain->status = get_equivalent_status_(status);
2266                         return false;
2267                 }
2268                 if(!write_metadata_block_data_(tempfile, &status, node->data)) {
2269                         chain->status = get_equivalent_status_(status);
2270                         return false;
2271                 }
2272         }
2273         /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
2274
2275         /* copy the file postfix (everything after the metadata) */
2276         if(0 != fseek(f, chain->last_offset, SEEK_SET)) {
2277                 cleanup_tempfile_(&tempfile, &tempfilename);
2278                 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2279                 return false;
2280         }
2281         if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) {
2282                 cleanup_tempfile_(&tempfile, &tempfilename);
2283                 chain->status = get_equivalent_status_(status);
2284                 return false;
2285         }
2286
2287         /* move the tempfile on top of the original */
2288         (void)fclose(f);
2289         if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
2290                 return false;
2291
2292         return true;
2293 }
2294
2295 void simple_iterator_push_(FLAC__MetaData_SimpleIterator *iterator)
2296 {
2297         FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH);
2298         iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth];
2299         iterator->depth++;
2300 }
2301
2302 FLAC__bool simple_iterator_pop_(FLAC__MetaData_SimpleIterator *iterator)
2303 {
2304         FLAC__ASSERT(iterator->depth > 0);
2305         iterator->depth--;
2306         if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2307                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2308                 return false;
2309         }
2310
2311         return read_metadata_block_header_(iterator);
2312 }
2313
2314 unsigned seek_to_first_metadata_block_(FILE *f)
2315 {
2316         FLAC__byte buffer[4];
2317         size_t n;
2318         unsigned i;
2319
2320         FLAC__ASSERT(0 != f);
2321         FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
2322
2323         /* skip any id3v2 tag */
2324         errno = 0;
2325         n = fread(buffer, 1, 4, f);
2326         if(errno)
2327                 return 1;
2328         else if(n != 4)
2329                 return 2;
2330         else if(0 == memcmp(buffer, "ID3", 3)) {
2331                 unsigned tag_length = 0;
2332
2333                 /* skip to the tag length */
2334                 if(fseek(f, 2, SEEK_CUR) < 0)
2335                         return 1;
2336
2337                 /* read the length */
2338                 for(i = 0; i < 4; i++) {
2339                         if(fread(buffer, 1, 1, f) < 1 || buffer[0] & 0x80)
2340                                 return 1;
2341                         tag_length <<= 7;
2342                         tag_length |= (buffer[0] & 0x7f);
2343                 }
2344
2345                 /* skip the rest of the tag */
2346                 if(fseek(f, tag_length, SEEK_CUR) < 0)
2347                         return 1;
2348
2349                 /* read the stream sync code */
2350                 errno = 0;
2351                 n = fread(buffer, 1, 4, f);
2352                 if(errno)
2353                         return 1;
2354                 else if(n != 4)
2355                         return 2;
2356         }
2357
2358         /* check for the fLaC signature */
2359         if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH))
2360                 return 0;
2361         else
2362                 return 2;
2363 }
2364
2365 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__MetaData_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
2366 {
2367         const long offset_end = append? iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length : iterator->offset[iterator->depth];
2368
2369         if(0 != fseek(iterator->file, 0, SEEK_SET)) {
2370                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2371                 return false;
2372         }
2373         if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) {
2374                 cleanup_tempfile_(tempfile, tempfilename);
2375                 return false;
2376         }
2377         if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) {
2378                 cleanup_tempfile_(tempfile, tempfilename);
2379                 return false;
2380         }
2381
2382         return true;
2383 }
2384
2385 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)
2386 {
2387         long save_offset = iterator->offset[iterator->depth]; /*@@@ 2G limit */
2388         FLAC__ASSERT(0 != *tempfile);
2389
2390         if(0 != fseek(iterator->file, save_offset + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length, SEEK_SET)) {
2391                 cleanup_tempfile_(tempfile, tempfilename);
2392                 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2393                 return false;
2394         }
2395         if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) {
2396                 cleanup_tempfile_(tempfile, tempfilename);
2397                 return false;
2398         }
2399
2400         if(fixup_is_last_code != 0) {
2401                 /*
2402                  * if code == 1, it means a block was appended to the end so
2403                  *   we have to clear the is_last flag of the previous block
2404                  * if code == -1, it means the last block was deleted so
2405                  *   we have to set the is_last flag of the previous block
2406                  */
2407                 /*@@@ MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
2408                 FLAC__byte x;
2409                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2410                         cleanup_tempfile_(tempfile, tempfilename);
2411                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2412                         return false;
2413                 }
2414                 if(fread(&x, 1, 1, *tempfile) != 1) {
2415                         cleanup_tempfile_(tempfile, tempfilename);
2416                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2417                         return false;
2418                 }
2419                 if(fixup_is_last_code > 0) {
2420                         FLAC__ASSERT(x & 0x80);
2421                         x &= 0x7f;
2422                 }
2423                 else {
2424                         FLAC__ASSERT(!(x & 0x80));
2425                         x |= 0x80;
2426                 }
2427                 if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2428                         cleanup_tempfile_(tempfile, tempfilename);
2429                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2430                         return false;
2431                 }
2432                 if(fwrite(&x, 1, 1, *tempfile) != 1) {
2433                         cleanup_tempfile_(tempfile, tempfilename);
2434                         iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2435                         return false;
2436                 }
2437         }
2438
2439         (void)fclose(iterator->file);
2440
2441         if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status))
2442                 return false;
2443
2444         if(iterator->has_stats)
2445                 set_file_stats_(iterator->filename, &iterator->stats);
2446
2447         if(!simple_iterator_prime_input_(iterator))
2448                 return false;
2449         if(backup) {
2450                 while(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length < save_offset)
2451                         if(!FLAC__metadata_simple_iterator_next(iterator))
2452                                 return false;
2453                 return true;
2454         }
2455         else {
2456                 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */
2457                 FLAC__ASSERT(iterator->depth == 0);
2458                 iterator->offset[0] = save_offset;
2459                 iterator->depth++;
2460                 return simple_iterator_pop_(iterator);
2461         }
2462 }
2463
2464 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__MetaData_SimpleIteratorStatus *status)
2465 {
2466         FLAC__byte buffer[8192];
2467         unsigned n;
2468
2469         while(bytes > 0) {
2470                 n = min(sizeof(buffer), bytes);
2471                 if(fread(buffer, 1, n, file) != n) {
2472                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2473                         return false;
2474                 }
2475                 if(fwrite(buffer, 1, n, tempfile) != n) {
2476                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2477                         return false;
2478                 }
2479                 bytes -= n;
2480         }
2481
2482         return true;
2483 }
2484
2485 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__MetaData_SimpleIteratorStatus *status)
2486 {
2487         FLAC__byte buffer[8192];
2488         size_t n;
2489
2490         while(!feof(file)) {
2491                 n = fread(buffer, 1, sizeof(buffer), file);
2492                 if(n == 0 && !feof(file)) {
2493                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2494                         return false;
2495                 }
2496                 if(n > 0 && fwrite(buffer, 1, n, tempfile) != n) {
2497                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
2498                         return false;
2499                 }
2500         }
2501
2502         return true;
2503 }
2504
2505 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status)
2506 {
2507         static const char *tempfile_suffix = ".metadata_edit";
2508         if(0 == tempfile_path_prefix) {
2509                 if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) {
2510                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2511                         return false;
2512                 }
2513                 strcpy(*tempfilename, filename);
2514                 strcat(*tempfilename, tempfile_suffix);
2515         }
2516         else {
2517                 const char *p = strrchr(filename, '/');
2518                 if(0 == p)
2519                         p = filename;
2520                 else
2521                         p++;
2522
2523                 if(0 == (*tempfilename = malloc(strlen(tempfile_path_prefix) + 1 + strlen(p) + strlen(tempfile_suffix) + 1))) {
2524                         *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2525                         return false;
2526                 }
2527                 strcpy(*tempfilename, tempfile_path_prefix);
2528                 strcat(*tempfilename, "/");
2529                 strcat(*tempfilename, p);
2530                 strcat(*tempfilename, tempfile_suffix);
2531         }
2532
2533         if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) {
2534                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
2535                 return false;
2536         }
2537
2538         return true;
2539 }
2540
2541 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__MetaData_SimpleIteratorStatus *status)
2542 {
2543         FLAC__ASSERT(0 != filename);
2544         FLAC__ASSERT(0 != tempfile);
2545         FLAC__ASSERT(0 != *tempfile);
2546         FLAC__ASSERT(0 != tempfilename);
2547         FLAC__ASSERT(0 != *tempfilename);
2548         FLAC__ASSERT(0 != status);
2549
2550         (void)fclose(*tempfile);
2551         *tempfile = 0;
2552         /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */
2553         if(0 != rename(*tempfilename, filename)) {
2554                 cleanup_tempfile_(tempfile, tempfilename);
2555                 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
2556                 return false;
2557         }
2558
2559         cleanup_tempfile_(tempfile, tempfilename);
2560
2561         return true;
2562 }
2563
2564 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
2565 {
2566         if(0 != *tempfile) {
2567                 (void)fclose(*tempfile);
2568                 *tempfile = 0;
2569         }
2570
2571         if(0 != *tempfilename) {
2572                 (void)unlink(*tempfilename);
2573                 free(*tempfilename);
2574                 *tempfilename = 0;
2575         }
2576 }
2577
2578 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
2579 {
2580         FLAC__ASSERT(0 != filename);
2581         FLAC__ASSERT(0 != stats);
2582         return (0 == stat(filename, stats));
2583 }
2584
2585 void set_file_stats_(const char *filename, struct stat *stats)
2586 {
2587         struct utimbuf srctime;
2588
2589         FLAC__ASSERT(0 != filename);
2590         FLAC__ASSERT(0 != stats);
2591
2592         srctime.actime = stats->st_atime;
2593         srctime.modtime = stats->st_mtime;
2594         (void)chmod(filename, stats->st_mode);
2595         (void)utime(filename, &srctime);
2596 #if !defined _MSC_VER && !defined __MINGW32__
2597         (void)chown(filename, stats->st_uid, -1);
2598         (void)chown(filename, -1, stats->st_gid);
2599 #endif
2600 }
2601
2602 FLAC__MetaData_ChainStatus get_equivalent_status_(FLAC__MetaData_SimpleIteratorStatus status)
2603 {
2604         switch(status) {
2605                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK:
2606                         return FLAC__METADATA_CHAIN_STATUS_OK;
2607                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
2608                         return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT;
2609                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
2610                         return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
2611                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
2612                         return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE;
2613                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE:
2614                         return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE;
2615                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA:
2616                         return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA;
2617                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR:
2618                         return FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
2619                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR:
2620                         return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
2621                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR:
2622                         return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
2623                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR:
2624                         return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR;
2625                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR:
2626                         return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR;
2627                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR:
2628                         return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
2629                 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR:
2630                 default:
2631                         return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
2632         }
2633 }
2634 #if 0
2635 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2636 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2637 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2638 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2639 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2640 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2641 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2642 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2643 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2644 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2645 FLAC__bool list(FILE *f, FLAC__bool verbose)
2646 {
2647         FLAC__byte buf[65536];
2648         FLAC__byte *b = buf;
2649         FLAC__StreamMetaData metadata;
2650         unsigned blocknum = 0, byte_offset = 0, i;
2651
2652         /* skip any id3v2 tag */
2653         if(fread(buf, 1, 4, f) < 4) {
2654                 fprintf(stderr, "ERROR: not a FLAC file\n");
2655                 return false;
2656         }
2657         if(0 == memcmp(buf, "ID3", 3)) {
2658                 unsigned tag_length = 0;
2659
2660                 /* skip to the tag length */
2661                 if(fseek(f, 2, SEEK_CUR) < 0) {
2662                         fprintf(stderr, "ERROR: bad ID3v2 tag\n");
2663                         return false;
2664                 }
2665
2666                 /* read the length */
2667                 for(i = 0; i < 4; i++) {
2668                         if(fread(buf, 1, 1, f) < 1 || buf[0] & 0x80) {
2669                                 fprintf(stderr, "ERROR: bad ID3v2 tag\n");
2670                                 return false;
2671                         }
2672                         tag_length <<= 7;
2673                         tag_length |= (buf[0] & 0x7f);
2674                 }
2675
2676                 /* skip the rest of the tag */
2677                 if(fseek(f, tag_length, SEEK_CUR) < 0) {
2678                         fprintf(stderr, "ERROR: bad ID3v2 tag\n");
2679                         return false;
2680                 }
2681
2682                 /* read the stream sync code */
2683                 if(fread(buf, 1, 4, f) < 4) {
2684                         fprintf(stderr, "ERROR: not a FLAC file (no '%s' header)\n", sync_string_);
2685                         return false;
2686                 }
2687         }
2688
2689         /* check the stream sync code */
2690         if(memcmp(buf, sync_string_, 4)) {
2691                 fprintf(stderr, "ERROR: not a FLAC file (no '%s' header)\n", sync_string_);
2692                 return false;
2693         }
2694         byte_offset += 4;
2695
2696         /* read the metadata blocks */
2697         do {
2698                 /* read the metadata block header */
2699                 if(fread(buf, 1, 4, f) < 4) {
2700                         fprintf(stderr, "ERROR: short count reading metadata block header\n");
2701                         return false;
2702                 }
2703                 metadata.is_last = (buf[0] & 0x80)? true:false;
2704                 metadata.type = (FLAC__MetaDataType)(buf[0] & 0x7f);
2705                 metadata.length = unpack_uint32(buf+1, 3);
2706
2707                 /* print header */
2708                 printf("METADATA block #%u\n", blocknum);
2709                 printf("  byte offset: %u\n", byte_offset);
2710                 printf("  type: %u (%s)\n", (unsigned)metadata.type, metadata.type<=FLAC__METADATA_TYPE_SEEKTABLE? metadata_type_string_[metadata.type] : "UNKNOWN");
2711                 printf("  is last: %s\n", metadata.is_last? "true":"false");
2712                 printf("  length: %u\n", metadata.length);
2713
2714                 if(metadata.length > sizeof(buf)) {
2715                         printf("  SKIPPING large block\n");
2716                         if(fseek(f, metadata.length, SEEK_CUR) < 0) {
2717                                 fprintf(stderr, "ERROR: short count skipping metadata block data\n");
2718                                 return false;
2719                         }
2720                         continue;
2721                 }
2722
2723                 /* read the metadata block data */
2724                 if(fread(buf, 1, metadata.length, f) < metadata.length) {
2725                         fprintf(stderr, "ERROR: short count reading metadata block data\n");
2726                         return false;
2727                 }
2728                 switch(metadata.type) {
2729                         case FLAC__METADATA_TYPE_STREAMINFO:
2730                                 b = buf;
2731                                 metadata.data.stream_info.min_blocksize = unpack_uint32(b, 2); b += 2;
2732                                 metadata.data.stream_info.max_blocksize = unpack_uint32(b, 2); b += 2;
2733                                 metadata.data.stream_info.min_framesize = unpack_uint32(b, 3); b += 3;
2734                                 metadata.data.stream_info.max_framesize = unpack_uint32(b, 3); b += 3;
2735                                 metadata.data.stream_info.sample_rate = (unpack_uint32(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
2736                                 metadata.data.stream_info.channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
2737                                 metadata.data.stream_info.bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 1) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
2738                                 metadata.data.stream_info.total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64(b+4, 4);
2739                                 memcpy(metadata.data.stream_info.md5sum, b+8, 16);
2740                                 break;
2741                         case FLAC__METADATA_TYPE_PADDING:
2742                                 if(verbose) {
2743                                         /* dump contents */
2744                                 }
2745                                 break;
2746                         case FLAC__METADATA_TYPE_APPLICATION:
2747                                 memcpy(metadata.data.application.id, buf, 4);
2748                                 metadata.data.application.data = buf+4;
2749                                 break;
2750                         case FLAC__METADATA_TYPE_SEEKTABLE:
2751                                 metadata.data.seek_table.num_points = metadata.length / SEEKPOINT_LEN_;
2752                                 b = buf; /* we leave the points in buf for printing later */
2753                                 break;
2754                         default:
2755                                 printf("SKIPPING block of unknown type\n");
2756                                 continue;
2757                 }
2758
2759                 /* print data */
2760                 switch(metadata.type) {
2761                         case FLAC__METADATA_TYPE_STREAMINFO:
2762                                 printf("  minumum blocksize: %u samples\n", metadata.data.stream_info.min_blocksize);
2763                                 printf("  maximum blocksize: %u samples\n", metadata.data.stream_info.max_blocksize);
2764                                 printf("  minimum framesize: %u bytes\n", metadata.data.stream_info.min_framesize);
2765                                 printf("  maximum framesize: %u bytes\n", metadata.data.stream_info.max_framesize);
2766                                 printf("  sample_rate: %u Hz\n", metadata.data.stream_info.sample_rate);
2767                                 printf("  channels: %u\n", metadata.data.stream_info.channels);
2768                                 printf("  bits-per-sample: %u\n", metadata.data.stream_info.bits_per_sample);
2769                                 printf("  total samples: %llu\n", metadata.data.stream_info.total_samples);
2770                                 printf("  MD5 signature: ");
2771                                 for(i = 0; i < 16; i++)
2772                                         printf("%02x", metadata.data.stream_info.md5sum[i]);
2773                                 printf("\n");
2774                                 break;
2775                         case FLAC__METADATA_TYPE_PADDING:
2776                                 if(verbose) {
2777                                         printf("  pad contents:\n");
2778                                         hexdump(buf, metadata.length, "    ");
2779                                 }
2780                                 break;
2781                         case FLAC__METADATA_TYPE_APPLICATION:
2782                                 printf("  application ID: ");
2783                                 for(i = 0; i < 4; i++)
2784                                         printf("%02x", metadata.data.application.id[i]);
2785                                 printf("\n");
2786                                 if(verbose) {
2787                                         printf("  data contents:\n");
2788                                         hexdump(metadata.data.application.data, metadata.length, "    ");
2789                                 }
2790                                 break;
2791                         case FLAC__METADATA_TYPE_SEEKTABLE:
2792                                 printf("  seek points: %u\n", metadata.data.seek_table.num_points);
2793                                 if(verbose) {
2794                                         for(i = 0; i < metadata.data.seek_table.num_points; i++, b += SEEKPOINT_LEN_)
2795                                                 printf("    point %d: sample_number=%llu, stream_offset=%llu, frame_samples=%u\n", i, unpack_uint64(b, 8), unpack_uint64(b+8, 8), unpack_uint32(b+16, 2));
2796                                 }
2797                                 break;
2798                         default:
2799                                 FLAC__ASSERT(0);
2800                 }
2801
2802                 blocknum++;
2803                 byte_offset += (4 + metadata.length);
2804         } while (!metadata.is_last);
2805
2806         return true;
2807 }
2808
2809 FLAC__uint32 unpack_uint32(FLAC__byte *b, unsigned bytes)
2810 {
2811         FLAC__uint32 ret = 0;
2812         unsigned i;
2813
2814         for(i = 0; i < bytes; i++)
2815                 ret = (ret << 8) | (FLAC__uint32)(*b++);
2816
2817         return ret;
2818 }
2819
2820 FLAC__uint64 unpack_uint64(FLAC__byte *b, unsigned bytes)
2821 {
2822         FLAC__uint64 ret = 0;
2823         unsigned i;
2824
2825         for(i = 0; i < bytes; i++)
2826                 ret = (ret << 8) | (FLAC__uint64)(*b++);
2827
2828         return ret;
2829 }
2830
2831 void hexdump(const FLAC__byte *buf, unsigned bytes, const char *indent)
2832 {
2833         unsigned i, left = bytes;
2834         const FLAC__byte *b = buf;
2835
2836         for(i = 0; i < bytes; i += 16) {
2837                 printf("%s%08X: "
2838                         "%02X %02X %02X %02X %02X %02X %02X %02X "
2839                         "%02X %02X %02X %02X %02X %02X %02X %02X "
2840                         "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
2841                         indent, i,
2842                         left >  0? (unsigned char)b[ 0] : 0,
2843                         left >  1? (unsigned char)b[ 1] : 0,
2844                         left >  2? (unsigned char)b[ 2] : 0,
2845                         left >  3? (unsigned char)b[ 3] : 0,
2846                         left >  4? (unsigned char)b[ 4] : 0,
2847                         left >  5? (unsigned char)b[ 5] : 0,
2848                         left >  6? (unsigned char)b[ 6] : 0,
2849                         left >  7? (unsigned char)b[ 7] : 0,
2850                         left >  8? (unsigned char)b[ 8] : 0,
2851                         left >  9? (unsigned char)b[ 9] : 0,
2852                         left > 10? (unsigned char)b[10] : 0,
2853                         left > 11? (unsigned char)b[11] : 0,
2854                         left > 12? (unsigned char)b[12] : 0,
2855                         left > 13? (unsigned char)b[13] : 0,
2856                         left > 14? (unsigned char)b[14] : 0,
2857                         left > 15? (unsigned char)b[15] : 0,
2858                         (left >  0) ? (isprint(b[ 0]) ? b[ 0] : '.') : ' ',
2859                         (left >  1) ? (isprint(b[ 1]) ? b[ 1] : '.') : ' ',
2860                         (left >  2) ? (isprint(b[ 2]) ? b[ 2] : '.') : ' ',
2861                         (left >  3) ? (isprint(b[ 3]) ? b[ 3] : '.') : ' ',
2862                         (left >  4) ? (isprint(b[ 4]) ? b[ 4] : '.') : ' ',
2863                         (left >  5) ? (isprint(b[ 5]) ? b[ 5] : '.') : ' ',
2864                         (left >  6) ? (isprint(b[ 6]) ? b[ 6] : '.') : ' ',
2865                         (left >  7) ? (isprint(b[ 7]) ? b[ 7] : '.') : ' ',
2866                         (left >  8) ? (isprint(b[ 8]) ? b[ 8] : '.') : ' ',
2867                         (left >  9) ? (isprint(b[ 9]) ? b[ 9] : '.') : ' ',
2868                         (left > 10) ? (isprint(b[10]) ? b[10] : '.') : ' ',
2869                         (left > 11) ? (isprint(b[11]) ? b[11] : '.') : ' ',
2870                         (left > 12) ? (isprint(b[12]) ? b[12] : '.') : ' ',
2871                         (left > 13) ? (isprint(b[13]) ? b[13] : '.') : ' ',
2872                         (left > 14) ? (isprint(b[14]) ? b[14] : '.') : ' ',
2873                         (left > 15) ? (isprint(b[15]) ? b[15] : '.') : ' '
2874                 );
2875                 left -= 16;
2876                 b += 16;
2877    }
2878 }
2879 #endif