1 /* libFLAC - Free Lossless Audio Codec library 2 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of the Xiph.org Foundation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_CONFIG_H 33 # include <config.h> 34 #endif 35 36 #include <errno.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 #if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ 42 #if defined __BORLANDC__ 43 #include <utime.h> /* for utime() */ 44 #else 45 #include <sys/utime.h> /* for utime() */ 46 #endif 47 #include <io.h> /* for chmod() */ 48 #include <sys/types.h> /* for off_t */ 49 #if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ 50 #define fseeko fseek 51 #define ftello ftell 52 #endif 53 #else 54 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */ 55 #include <utime.h> /* for utime() */ 56 #include <unistd.h> /* for chown(), unlink() */ 57 #endif 58 #include <sys/stat.h> /* for stat(), maybe chmod() */ 59 60 #include "private/metadata.h" 61 62 #include "FLAC/assert.h" 63 #include "FLAC/stream_decoder.h" 64 #include "share/alloc.h" 65 66 #ifdef max 67 #undef max 68 #endif 69 #define max(a,b) ((a)>(b)?(a):(b)) 70 #ifdef min 71 #undef min 72 #endif 73 #define min(a,b) ((a)<(b)?(a):(b)) 74 75 76 /**************************************************************************** 77 * 78 * Local function declarations 79 * 80 ***************************************************************************/ 81 82 static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 83 static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 84 static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes); 85 static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes); 86 static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes); 87 static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes); 88 89 static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator); 90 static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block); 91 static FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length); 92 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block); 93 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block); 94 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length); 95 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length); 96 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); 97 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry); 98 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block); 99 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track); 100 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block); 101 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block); 102 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length); 103 104 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 105 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 106 static FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 107 static FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 108 static FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block); 109 static FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length); 110 static FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length); 111 static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block); 112 static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block); 113 static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block); 114 static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block); 115 static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length); 116 117 static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block); 118 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last); 119 static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append); 120 121 static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator); 122 static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator); 123 124 static unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb); 125 static unsigned seek_to_first_metadata_block_(FILE *f); 126 127 static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append); 128 static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup); 129 130 static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); 131 static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); 132 static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status); 133 static FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status); 134 135 static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 136 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 137 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename); 138 139 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats); 140 static void set_file_stats_(const char *filename, struct stat *stats); 141 142 static int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence); 143 static FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle); 144 145 static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status); 146 147 148 #ifdef FLAC__VALGRIND_TESTING 149 static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 150 { 151 size_t ret = fwrite(ptr, size, nmemb, stream); 152 if(!ferror(stream)) 153 fflush(stream); 154 return ret; 155 } 156 #else 157 #define local__fwrite fwrite 158 #endif 159 160 /**************************************************************************** 161 * 162 * Level 0 implementation 163 * 164 ***************************************************************************/ 165 166 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); 167 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); 168 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); 169 170 typedef struct { 171 FLAC__bool got_error; 172 FLAC__StreamMetadata *object; 173 } level0_client_data; 174 175 static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type) 176 { 177 level0_client_data cd; 178 FLAC__StreamDecoder *decoder; 179 180 FLAC__ASSERT(0 != filename); 181 182 cd.got_error = false; 183 cd.object = 0; 184 185 decoder = FLAC__stream_decoder_new(); 186 187 if(0 == decoder) 188 return 0; 189 190 FLAC__stream_decoder_set_md5_checking(decoder, false); 191 FLAC__stream_decoder_set_metadata_ignore_all(decoder); 192 FLAC__stream_decoder_set_metadata_respond(decoder, type); 193 194 if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) { 195 (void)FLAC__stream_decoder_finish(decoder); 196 FLAC__stream_decoder_delete(decoder); 197 return 0; 198 } 199 200 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) { 201 (void)FLAC__stream_decoder_finish(decoder); 202 FLAC__stream_decoder_delete(decoder); 203 if(0 != cd.object) 204 FLAC__metadata_object_delete(cd.object); 205 return 0; 206 } 207 208 (void)FLAC__stream_decoder_finish(decoder); 209 FLAC__stream_decoder_delete(decoder); 210 211 return cd.object; 212 } 213 214 FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo) 215 { 216 FLAC__StreamMetadata *object; 217 218 FLAC__ASSERT(0 != filename); 219 FLAC__ASSERT(0 != streaminfo); 220 221 object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO); 222 223 if (object) { 224 /* can just copy the contents since STREAMINFO has no internal structure */ 225 *streaminfo = *object; 226 FLAC__metadata_object_delete(object); 227 return true; 228 } 229 else { 230 return false; 231 } 232 } 233 234 FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags) 235 { 236 FLAC__ASSERT(0 != filename); 237 FLAC__ASSERT(0 != tags); 238 239 *tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT); 240 241 return 0 != *tags; 242 } 243 244 FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet) 245 { 246 FLAC__ASSERT(0 != filename); 247 FLAC__ASSERT(0 != cuesheet); 248 249 *cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET); 250 251 return 0 != *cuesheet; 252 } 253 254 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) 255 { 256 (void)decoder, (void)frame, (void)buffer, (void)client_data; 257 258 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; 259 } 260 261 void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) 262 { 263 level0_client_data *cd = (level0_client_data *)client_data; 264 (void)decoder; 265 266 /* 267 * we assume we only get here when the one metadata block we were 268 * looking for was passed to us 269 */ 270 if(!cd->got_error && 0 == cd->object) { 271 if(0 == (cd->object = FLAC__metadata_object_clone(metadata))) 272 cd->got_error = true; 273 } 274 } 275 276 void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 277 { 278 level0_client_data *cd = (level0_client_data *)client_data; 279 (void)decoder; 280 281 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) 282 cd->got_error = true; 283 } 284 285 FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors) 286 { 287 FLAC__Metadata_SimpleIterator *it; 288 FLAC__uint64 max_area_seen = 0; 289 FLAC__uint64 max_depth_seen = 0; 290 291 FLAC__ASSERT(0 != filename); 292 FLAC__ASSERT(0 != picture); 293 294 *picture = 0; 295 296 it = FLAC__metadata_simple_iterator_new(); 297 if(0 == it) 298 return false; 299 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) { 300 FLAC__metadata_simple_iterator_delete(it); 301 return false; 302 } 303 do { 304 if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) { 305 FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it); 306 FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height; 307 /* check constraints */ 308 if( 309 (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) && 310 (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) && 311 (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) && 312 obj->data.picture.width <= max_width && 313 obj->data.picture.height <= max_height && 314 obj->data.picture.depth <= max_depth && 315 obj->data.picture.colors <= max_colors && 316 (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen)) 317 ) { 318 if(*picture) 319 FLAC__metadata_object_delete(*picture); 320 *picture = obj; 321 max_area_seen = area; 322 max_depth_seen = obj->data.picture.depth; 323 } 324 else { 325 FLAC__metadata_object_delete(obj); 326 } 327 } 328 } while(FLAC__metadata_simple_iterator_next(it)); 329 330 FLAC__metadata_simple_iterator_delete(it); 331 332 return (0 != *picture); 333 } 334 335 336 /**************************************************************************** 337 * 338 * Level 1 implementation 339 * 340 ***************************************************************************/ 341 342 #define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4) 343 /* 1 for initial offset, +4 for our own personal use */ 344 345 struct FLAC__Metadata_SimpleIterator { 346 FILE *file; 347 char *filename, *tempfile_path_prefix; 348 struct stat stats; 349 FLAC__bool has_stats; 350 FLAC__bool is_writable; 351 FLAC__Metadata_SimpleIteratorStatus status; 352 off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH]; 353 off_t first_offset; /* this is the offset to the STREAMINFO block */ 354 unsigned depth; 355 /* this is the metadata block header of the current block we are pointing to: */ 356 FLAC__bool is_last; 357 FLAC__MetadataType type; 358 unsigned length; 359 }; 360 361 FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = { 362 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK", 363 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT", 364 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE", 365 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE", 366 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE", 367 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA", 368 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR", 369 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR", 370 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR", 371 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR", 372 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR", 373 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR", 374 "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR" 375 }; 376 377 378 FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void) 379 { 380 FLAC__Metadata_SimpleIterator *iterator = (FLAC__Metadata_SimpleIterator*)calloc(1, sizeof(FLAC__Metadata_SimpleIterator)); 381 382 if(0 != iterator) { 383 iterator->file = 0; 384 iterator->filename = 0; 385 iterator->tempfile_path_prefix = 0; 386 iterator->has_stats = false; 387 iterator->is_writable = false; 388 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 389 iterator->first_offset = iterator->offset[0] = -1; 390 iterator->depth = 0; 391 } 392 393 return iterator; 394 } 395 396 static void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator) 397 { 398 FLAC__ASSERT(0 != iterator); 399 400 if(0 != iterator->file) { 401 fclose(iterator->file); 402 iterator->file = 0; 403 if(iterator->has_stats) 404 set_file_stats_(iterator->filename, &iterator->stats); 405 } 406 if(0 != iterator->filename) { 407 free(iterator->filename); 408 iterator->filename = 0; 409 } 410 if(0 != iterator->tempfile_path_prefix) { 411 free(iterator->tempfile_path_prefix); 412 iterator->tempfile_path_prefix = 0; 413 } 414 } 415 416 FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator) 417 { 418 FLAC__ASSERT(0 != iterator); 419 420 simple_iterator_free_guts_(iterator); 421 free(iterator); 422 } 423 424 FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator) 425 { 426 FLAC__Metadata_SimpleIteratorStatus status; 427 428 FLAC__ASSERT(0 != iterator); 429 430 status = iterator->status; 431 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 432 return status; 433 } 434 435 static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool read_only) 436 { 437 unsigned ret; 438 439 FLAC__ASSERT(0 != iterator); 440 441 if(read_only || 0 == (iterator->file = fopen(iterator->filename, "r+b"))) { 442 iterator->is_writable = false; 443 if(read_only || errno == EACCES) { 444 if(0 == (iterator->file = fopen(iterator->filename, "rb"))) { 445 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 446 return false; 447 } 448 } 449 else { 450 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 451 return false; 452 } 453 } 454 else { 455 iterator->is_writable = true; 456 } 457 458 ret = seek_to_first_metadata_block_(iterator->file); 459 switch(ret) { 460 case 0: 461 iterator->depth = 0; 462 iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file); 463 return read_metadata_block_header_(iterator); 464 case 1: 465 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 466 return false; 467 case 2: 468 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 469 return false; 470 case 3: 471 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE; 472 return false; 473 default: 474 FLAC__ASSERT(0); 475 return false; 476 } 477 } 478 479 #if 0 480 @@@ If we decide to finish implementing this, put this comment back in metadata.h 481 /* 482 * The 'tempfile_path_prefix' allows you to specify a directory where 483 * tempfiles should go. Remember that if your metadata edits cause the 484 * FLAC file to grow, the entire file will have to be rewritten. If 485 * 'tempfile_path_prefix' is NULL, the temp file will be written in the 486 * same directory as the original FLAC file. This makes replacing the 487 * original with the tempfile fast but requires extra space in the same 488 * partition for the tempfile. If space is a problem, you can pass a 489 * directory name belonging to a different partition in 490 * 'tempfile_path_prefix'. Note that you should use the forward slash 491 * '/' as the directory separator. A trailing slash is not needed; it 492 * will be added automatically. 493 */ 494 FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix); 495 #endif 496 497 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats) 498 { 499 const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */ 500 501 FLAC__ASSERT(0 != iterator); 502 FLAC__ASSERT(0 != filename); 503 504 simple_iterator_free_guts_(iterator); 505 506 if(!read_only && preserve_file_stats) 507 iterator->has_stats = get_file_stats_(filename, &iterator->stats); 508 509 if(0 == (iterator->filename = strdup(filename))) { 510 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 511 return false; 512 } 513 if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) { 514 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 515 return false; 516 } 517 518 return simple_iterator_prime_input_(iterator, read_only); 519 } 520 521 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator) 522 { 523 FLAC__ASSERT(0 != iterator); 524 FLAC__ASSERT(0 != iterator->file); 525 526 return iterator->is_writable; 527 } 528 529 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator) 530 { 531 FLAC__ASSERT(0 != iterator); 532 FLAC__ASSERT(0 != iterator->file); 533 534 if(iterator->is_last) 535 return false; 536 537 if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { 538 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 539 return false; 540 } 541 542 iterator->offset[iterator->depth] = ftello(iterator->file); 543 544 return read_metadata_block_header_(iterator); 545 } 546 547 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator) 548 { 549 off_t this_offset; 550 551 FLAC__ASSERT(0 != iterator); 552 FLAC__ASSERT(0 != iterator->file); 553 554 if(iterator->offset[iterator->depth] == iterator->first_offset) 555 return false; 556 557 if(0 != fseeko(iterator->file, iterator->first_offset, SEEK_SET)) { 558 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 559 return false; 560 } 561 this_offset = iterator->first_offset; 562 if(!read_metadata_block_header_(iterator)) 563 return false; 564 565 /* we ignore any error from ftello() and catch it in fseeko() */ 566 while(ftello(iterator->file) + (off_t)iterator->length < iterator->offset[iterator->depth]) { 567 if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { 568 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 569 return false; 570 } 571 this_offset = ftello(iterator->file); 572 if(!read_metadata_block_header_(iterator)) 573 return false; 574 } 575 576 iterator->offset[iterator->depth] = this_offset; 577 578 return true; 579 } 580 581 /*@@@@add to tests*/ 582 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator) 583 { 584 FLAC__ASSERT(0 != iterator); 585 FLAC__ASSERT(0 != iterator->file); 586 587 return iterator->is_last; 588 } 589 590 /*@@@@add to tests*/ 591 FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator) 592 { 593 FLAC__ASSERT(0 != iterator); 594 FLAC__ASSERT(0 != iterator->file); 595 596 return iterator->offset[iterator->depth]; 597 } 598 599 FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator) 600 { 601 FLAC__ASSERT(0 != iterator); 602 FLAC__ASSERT(0 != iterator->file); 603 604 return iterator->type; 605 } 606 607 /*@@@@add to tests*/ 608 FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator) 609 { 610 FLAC__ASSERT(0 != iterator); 611 FLAC__ASSERT(0 != iterator->file); 612 613 return iterator->length; 614 } 615 616 /*@@@@add to tests*/ 617 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id) 618 { 619 const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 620 621 FLAC__ASSERT(0 != iterator); 622 FLAC__ASSERT(0 != iterator->file); 623 FLAC__ASSERT(0 != id); 624 625 if(iterator->type != FLAC__METADATA_TYPE_APPLICATION) { 626 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 627 return false; 628 } 629 630 if(fread(id, 1, id_bytes, iterator->file) != id_bytes) { 631 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 632 return false; 633 } 634 635 /* back up */ 636 if(0 != fseeko(iterator->file, -((int)id_bytes), SEEK_CUR)) { 637 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 638 return false; 639 } 640 641 return true; 642 } 643 644 FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator) 645 { 646 FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type); 647 648 FLAC__ASSERT(0 != iterator); 649 FLAC__ASSERT(0 != iterator->file); 650 651 if(0 != block) { 652 block->is_last = iterator->is_last; 653 block->length = iterator->length; 654 655 if(!read_metadata_block_data_(iterator, block)) { 656 FLAC__metadata_object_delete(block); 657 return 0; 658 } 659 660 /* back up to the beginning of the block data to stay consistent */ 661 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) { 662 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 663 FLAC__metadata_object_delete(block); 664 return 0; 665 } 666 } 667 else 668 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 669 670 return block; 671 } 672 673 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) 674 { 675 FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) 676 FLAC__bool ret; 677 678 FLAC__ASSERT(0 != iterator); 679 FLAC__ASSERT(0 != iterator->file); 680 FLAC__ASSERT(0 != block); 681 682 if(!iterator->is_writable) { 683 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE; 684 return false; 685 } 686 687 if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) { 688 if(iterator->type != block->type) { 689 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 690 return false; 691 } 692 } 693 694 block->is_last = iterator->is_last; 695 696 if(iterator->length == block->length) 697 return write_metadata_block_stationary_(iterator, block); 698 else if(iterator->length > block->length) { 699 if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) { 700 ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last); 701 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 702 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 703 return ret; 704 } 705 else { 706 ret = rewrite_whole_file_(iterator, block, /*append=*/false); 707 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 708 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 709 return ret; 710 } 711 } 712 else /* iterator->length < block->length */ { 713 unsigned padding_leftover = 0; 714 FLAC__bool padding_is_last = false; 715 if(use_padding) { 716 /* first see if we can even use padding */ 717 if(iterator->is_last) { 718 use_padding = false; 719 } 720 else { 721 const unsigned extra_padding_bytes_required = block->length - iterator->length; 722 simple_iterator_push_(iterator); 723 if(!FLAC__metadata_simple_iterator_next(iterator)) { 724 (void)simple_iterator_pop_(iterator); 725 return false; 726 } 727 if(iterator->type != FLAC__METADATA_TYPE_PADDING) { 728 use_padding = false; 729 } 730 else { 731 if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) { 732 padding_leftover = 0; 733 block->is_last = iterator->is_last; 734 } 735 else if(iterator->length < extra_padding_bytes_required) 736 use_padding = false; 737 else { 738 padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required; 739 padding_is_last = iterator->is_last; 740 block->is_last = false; 741 } 742 } 743 if(!simple_iterator_pop_(iterator)) 744 return false; 745 } 746 } 747 if(use_padding) { 748 if(padding_leftover == 0) { 749 ret = write_metadata_block_stationary_(iterator, block); 750 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 751 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 752 return ret; 753 } 754 else { 755 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); 756 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); 757 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 758 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 759 return ret; 760 } 761 } 762 else { 763 ret = rewrite_whole_file_(iterator, block, /*append=*/false); 764 FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 765 FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 766 return ret; 767 } 768 } 769 } 770 771 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) 772 { 773 unsigned padding_leftover = 0; 774 FLAC__bool padding_is_last = false; 775 776 FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;) 777 FLAC__bool ret; 778 779 FLAC__ASSERT(0 != iterator); 780 FLAC__ASSERT(0 != iterator->file); 781 FLAC__ASSERT(0 != block); 782 783 if(!iterator->is_writable) 784 return false; 785 786 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { 787 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 788 return false; 789 } 790 791 block->is_last = iterator->is_last; 792 793 if(use_padding) { 794 /* first see if we can even use padding */ 795 if(iterator->is_last) { 796 use_padding = false; 797 } 798 else { 799 simple_iterator_push_(iterator); 800 if(!FLAC__metadata_simple_iterator_next(iterator)) { 801 (void)simple_iterator_pop_(iterator); 802 return false; 803 } 804 if(iterator->type != FLAC__METADATA_TYPE_PADDING) { 805 use_padding = false; 806 } 807 else { 808 if(iterator->length == block->length) { 809 padding_leftover = 0; 810 block->is_last = iterator->is_last; 811 } 812 else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) 813 use_padding = false; 814 else { 815 padding_leftover = iterator->length - block->length; 816 padding_is_last = iterator->is_last; 817 block->is_last = false; 818 } 819 } 820 if(!simple_iterator_pop_(iterator)) 821 return false; 822 } 823 } 824 if(use_padding) { 825 /* move to the next block, which is suitable padding */ 826 if(!FLAC__metadata_simple_iterator_next(iterator)) 827 return false; 828 if(padding_leftover == 0) { 829 ret = write_metadata_block_stationary_(iterator, block); 830 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 831 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 832 return ret; 833 } 834 else { 835 FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); 836 ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); 837 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 838 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 839 return ret; 840 } 841 } 842 else { 843 ret = rewrite_whole_file_(iterator, block, /*append=*/true); 844 FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 845 FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 846 return ret; 847 } 848 } 849 850 FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding) 851 { 852 FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) 853 FLAC__bool ret; 854 855 if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) { 856 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 857 return false; 858 } 859 860 if(use_padding) { 861 FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); 862 if(0 == padding) { 863 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 864 return false; 865 } 866 padding->length = iterator->length; 867 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) { 868 FLAC__metadata_object_delete(padding); 869 return false; 870 } 871 FLAC__metadata_object_delete(padding); 872 if(!FLAC__metadata_simple_iterator_prev(iterator)) 873 return false; 874 FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); 875 FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); 876 return true; 877 } 878 else { 879 ret = rewrite_whole_file_(iterator, 0, /*append=*/false); 880 FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); 881 FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); 882 return ret; 883 } 884 } 885 886 887 888 /**************************************************************************** 889 * 890 * Level 2 implementation 891 * 892 ***************************************************************************/ 893 894 895 typedef struct FLAC__Metadata_Node { 896 FLAC__StreamMetadata *data; 897 struct FLAC__Metadata_Node *prev, *next; 898 } FLAC__Metadata_Node; 899 900 struct FLAC__Metadata_Chain { 901 char *filename; /* will be NULL if using callbacks */ 902 FLAC__bool is_ogg; 903 FLAC__Metadata_Node *head; 904 FLAC__Metadata_Node *tail; 905 unsigned nodes; 906 FLAC__Metadata_ChainStatus status; 907 off_t first_offset, last_offset; 908 /* 909 * This is the length of the chain initially read from the FLAC file. 910 * it is used to compare against the current length to decide whether 911 * or not the whole file has to be rewritten. 912 */ 913 off_t initial_length; 914 /* @@@ hacky, these are currently only needed by ogg reader */ 915 FLAC__IOHandle handle; 916 FLAC__IOCallback_Read read_cb; 917 }; 918 919 struct FLAC__Metadata_Iterator { 920 FLAC__Metadata_Chain *chain; 921 FLAC__Metadata_Node *current; 922 }; 923 924 FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = { 925 "FLAC__METADATA_CHAIN_STATUS_OK", 926 "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT", 927 "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE", 928 "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE", 929 "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE", 930 "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA", 931 "FLAC__METADATA_CHAIN_STATUS_READ_ERROR", 932 "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR", 933 "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR", 934 "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR", 935 "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR", 936 "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR", 937 "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR", 938 "FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS", 939 "FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", 940 "FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL" 941 }; 942 943 944 static FLAC__Metadata_Node *node_new_(void) 945 { 946 return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node)); 947 } 948 949 static void node_delete_(FLAC__Metadata_Node *node) 950 { 951 FLAC__ASSERT(0 != node); 952 if(0 != node->data) 953 FLAC__metadata_object_delete(node->data); 954 free(node); 955 } 956 957 static void chain_init_(FLAC__Metadata_Chain *chain) 958 { 959 FLAC__ASSERT(0 != chain); 960 961 chain->filename = 0; 962 chain->is_ogg = false; 963 chain->head = chain->tail = 0; 964 chain->nodes = 0; 965 chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 966 chain->initial_length = 0; 967 chain->read_cb = 0; 968 } 969 970 static void chain_clear_(FLAC__Metadata_Chain *chain) 971 { 972 FLAC__Metadata_Node *node, *next; 973 974 FLAC__ASSERT(0 != chain); 975 976 for(node = chain->head; node; ) { 977 next = node->next; 978 node_delete_(node); 979 node = next; 980 } 981 982 if(0 != chain->filename) 983 free(chain->filename); 984 985 chain_init_(chain); 986 } 987 988 static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 989 { 990 FLAC__ASSERT(0 != chain); 991 FLAC__ASSERT(0 != node); 992 FLAC__ASSERT(0 != node->data); 993 994 node->next = node->prev = 0; 995 node->data->is_last = true; 996 if(0 != chain->tail) 997 chain->tail->data->is_last = false; 998 999 if(0 == chain->head) 1000 chain->head = node; 1001 else { 1002 FLAC__ASSERT(0 != chain->tail); 1003 chain->tail->next = node; 1004 node->prev = chain->tail; 1005 } 1006 chain->tail = node; 1007 chain->nodes++; 1008 } 1009 1010 static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1011 { 1012 FLAC__ASSERT(0 != chain); 1013 FLAC__ASSERT(0 != node); 1014 1015 if(node == chain->head) 1016 chain->head = node->next; 1017 else 1018 node->prev->next = node->next; 1019 1020 if(node == chain->tail) 1021 chain->tail = node->prev; 1022 else 1023 node->next->prev = node->prev; 1024 1025 if(0 != chain->tail) 1026 chain->tail->data->is_last = true; 1027 1028 chain->nodes--; 1029 } 1030 1031 static void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1032 { 1033 chain_remove_node_(chain, node); 1034 node_delete_(node); 1035 } 1036 1037 static off_t chain_calculate_length_(FLAC__Metadata_Chain *chain) 1038 { 1039 const FLAC__Metadata_Node *node; 1040 off_t length = 0; 1041 for(node = chain->head; node; node = node->next) 1042 length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1043 return length; 1044 } 1045 1046 static void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) 1047 { 1048 FLAC__ASSERT(0 != node); 1049 FLAC__ASSERT(0 != node->data); 1050 FLAC__ASSERT(0 != iterator); 1051 FLAC__ASSERT(0 != iterator->current); 1052 FLAC__ASSERT(0 != iterator->chain); 1053 FLAC__ASSERT(0 != iterator->chain->head); 1054 FLAC__ASSERT(0 != iterator->chain->tail); 1055 1056 node->data->is_last = false; 1057 1058 node->prev = iterator->current->prev; 1059 node->next = iterator->current; 1060 1061 if(0 == node->prev) 1062 iterator->chain->head = node; 1063 else 1064 node->prev->next = node; 1065 1066 iterator->current->prev = node; 1067 1068 iterator->chain->nodes++; 1069 } 1070 1071 static void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) 1072 { 1073 FLAC__ASSERT(0 != node); 1074 FLAC__ASSERT(0 != node->data); 1075 FLAC__ASSERT(0 != iterator); 1076 FLAC__ASSERT(0 != iterator->current); 1077 FLAC__ASSERT(0 != iterator->chain); 1078 FLAC__ASSERT(0 != iterator->chain->head); 1079 FLAC__ASSERT(0 != iterator->chain->tail); 1080 1081 iterator->current->data->is_last = false; 1082 1083 node->prev = iterator->current; 1084 node->next = iterator->current->next; 1085 1086 if(0 == node->next) 1087 iterator->chain->tail = node; 1088 else 1089 node->next->prev = node; 1090 1091 node->prev->next = node; 1092 1093 iterator->chain->tail->data->is_last = true; 1094 1095 iterator->chain->nodes++; 1096 } 1097 1098 /* return true iff node and node->next are both padding */ 1099 static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1100 { 1101 if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) { 1102 const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length; 1103 node->data->length += growth; 1104 1105 chain_delete_node_(chain, node->next); 1106 return true; 1107 } 1108 else 1109 return false; 1110 } 1111 1112 /* Returns the new length of the chain, or 0 if there was an error. */ 1113 /* WATCHOUT: This can get called multiple times before a write, so 1114 * it should still work when this happens. 1115 */ 1116 /* WATCHOUT: Make sure to also update the logic in 1117 * FLAC__metadata_chain_check_if_tempfile_needed() if the logic here changes. 1118 */ 1119 static off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) 1120 { 1121 off_t current_length = chain_calculate_length_(chain); 1122 1123 if(use_padding) { 1124 /* if the metadata shrank and the last block is padding, we just extend the last padding block */ 1125 if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1126 const off_t delta = chain->initial_length - current_length; 1127 chain->tail->data->length += delta; 1128 current_length += delta; 1129 FLAC__ASSERT(current_length == chain->initial_length); 1130 } 1131 /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ 1132 else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) { 1133 FLAC__StreamMetadata *padding; 1134 FLAC__Metadata_Node *node; 1135 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) { 1136 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1137 return 0; 1138 } 1139 padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + current_length); 1140 if(0 == (node = node_new_())) { 1141 FLAC__metadata_object_delete(padding); 1142 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1143 return 0; 1144 } 1145 node->data = padding; 1146 chain_append_node_(chain, node); 1147 current_length = chain_calculate_length_(chain); 1148 FLAC__ASSERT(current_length == chain->initial_length); 1149 } 1150 /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ 1151 else if(current_length > chain->initial_length) { 1152 const off_t delta = current_length - chain->initial_length; 1153 if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1154 /* if the delta is exactly the size of the last padding block, remove the padding block */ 1155 if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) { 1156 chain_delete_node_(chain, chain->tail); 1157 current_length = chain_calculate_length_(chain); 1158 FLAC__ASSERT(current_length == chain->initial_length); 1159 } 1160 /* if there is at least 'delta' bytes of padding, trim the padding down */ 1161 else if((off_t)chain->tail->data->length >= delta) { 1162 chain->tail->data->length -= delta; 1163 current_length -= delta; 1164 FLAC__ASSERT(current_length == chain->initial_length); 1165 } 1166 } 1167 } 1168 } 1169 1170 return current_length; 1171 } 1172 1173 static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb) 1174 { 1175 FLAC__Metadata_Node *node; 1176 1177 FLAC__ASSERT(0 != chain); 1178 1179 /* we assume we're already at the beginning of the file */ 1180 1181 switch(seek_to_first_metadata_block_cb_(handle, read_cb, seek_cb)) { 1182 case 0: 1183 break; 1184 case 1: 1185 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1186 return false; 1187 case 2: 1188 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1189 return false; 1190 case 3: 1191 chain->status = FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; 1192 return false; 1193 default: 1194 FLAC__ASSERT(0); 1195 return false; 1196 } 1197 1198 { 1199 FLAC__int64 pos = tell_cb(handle); 1200 if(pos < 0) { 1201 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1202 return false; 1203 } 1204 chain->first_offset = (off_t)pos; 1205 } 1206 1207 { 1208 FLAC__bool is_last; 1209 FLAC__MetadataType type; 1210 unsigned length; 1211 1212 do { 1213 node = node_new_(); 1214 if(0 == node) { 1215 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1216 return false; 1217 } 1218 1219 if(!read_metadata_block_header_cb_(handle, read_cb, &is_last, &type, &length)) { 1220 node_delete_(node); 1221 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1222 return false; 1223 } 1224 1225 node->data = FLAC__metadata_object_new(type); 1226 if(0 == node->data) { 1227 node_delete_(node); 1228 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1229 return false; 1230 } 1231 1232 node->data->is_last = is_last; 1233 node->data->length = length; 1234 1235 chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data)); 1236 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1237 node_delete_(node); 1238 return false; 1239 } 1240 chain_append_node_(chain, node); 1241 } while(!is_last); 1242 } 1243 1244 { 1245 FLAC__int64 pos = tell_cb(handle); 1246 if(pos < 0) { 1247 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1248 return false; 1249 } 1250 chain->last_offset = (off_t)pos; 1251 } 1252 1253 chain->initial_length = chain_calculate_length_(chain); 1254 1255 return true; 1256 } 1257 1258 static FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) 1259 { 1260 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1261 (void)decoder; 1262 if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) { 1263 *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle); 1264 if(*bytes == 0) 1265 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; 1266 else 1267 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 1268 } 1269 else 1270 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 1271 } 1272 1273 static FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) 1274 { 1275 (void)decoder, (void)frame, (void)buffer, (void)client_data; 1276 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; 1277 } 1278 1279 static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) 1280 { 1281 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1282 FLAC__Metadata_Node *node; 1283 1284 (void)decoder; 1285 1286 node = node_new_(); 1287 if(0 == node) { 1288 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1289 return; 1290 } 1291 1292 node->data = FLAC__metadata_object_clone(metadata); 1293 if(0 == node->data) { 1294 node_delete_(node); 1295 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1296 return; 1297 } 1298 1299 chain_append_node_(chain, node); 1300 } 1301 1302 static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 1303 { 1304 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1305 (void)decoder, (void)status; 1306 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1307 } 1308 1309 static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb) 1310 { 1311 FLAC__StreamDecoder *decoder; 1312 1313 FLAC__ASSERT(0 != chain); 1314 1315 /* we assume we're already at the beginning of the file */ 1316 1317 chain->handle = handle; 1318 chain->read_cb = read_cb; 1319 if(0 == (decoder = FLAC__stream_decoder_new())) { 1320 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1321 return false; 1322 } 1323 FLAC__stream_decoder_set_metadata_respond_all(decoder); 1324 if(FLAC__stream_decoder_init_ogg_stream(decoder, chain_read_ogg_read_cb_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, chain_read_ogg_write_cb_, chain_read_ogg_metadata_cb_, chain_read_ogg_error_cb_, chain) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { 1325 FLAC__stream_decoder_delete(decoder); 1326 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1327 return false; 1328 } 1329 1330 chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1331 1332 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) 1333 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1334 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1335 FLAC__stream_decoder_delete(decoder); 1336 return false; 1337 } 1338 1339 FLAC__stream_decoder_delete(decoder); 1340 1341 chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1342 1343 chain->initial_length = chain_calculate_length_(chain); 1344 1345 return true; 1346 } 1347 1348 static FLAC__bool chain_rewrite_metadata_in_place_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, FLAC__IOCallback_Seek seek_cb) 1349 { 1350 FLAC__Metadata_Node *node; 1351 1352 FLAC__ASSERT(0 != chain); 1353 FLAC__ASSERT(0 != chain->head); 1354 1355 if(0 != seek_cb(handle, chain->first_offset, SEEK_SET)) { 1356 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1357 return false; 1358 } 1359 1360 for(node = chain->head; node; node = node->next) { 1361 if(!write_metadata_block_header_cb_(handle, write_cb, node->data)) { 1362 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1363 return false; 1364 } 1365 if(!write_metadata_block_data_cb_(handle, write_cb, node->data)) { 1366 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1367 return false; 1368 } 1369 } 1370 1371 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1372 1373 chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1374 return true; 1375 } 1376 1377 static FLAC__bool chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain *chain) 1378 { 1379 FILE *file; 1380 FLAC__bool ret; 1381 1382 FLAC__ASSERT(0 != chain->filename); 1383 1384 if(0 == (file = fopen(chain->filename, "r+b"))) { 1385 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1386 return false; 1387 } 1388 1389 /* chain_rewrite_metadata_in_place_cb_() sets chain->status for us */ 1390 ret = chain_rewrite_metadata_in_place_cb_(chain, (FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, fseek_wrapper_); 1391 1392 fclose(file); 1393 1394 return ret; 1395 } 1396 1397 static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix) 1398 { 1399 FILE *f, *tempfile; 1400 char *tempfilename; 1401 FLAC__Metadata_SimpleIteratorStatus status; 1402 const FLAC__Metadata_Node *node; 1403 1404 FLAC__ASSERT(0 != chain); 1405 FLAC__ASSERT(0 != chain->filename); 1406 FLAC__ASSERT(0 != chain->head); 1407 1408 /* copy the file prefix (data up to first metadata block */ 1409 if(0 == (f = fopen(chain->filename, "rb"))) { 1410 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1411 return false; 1412 } 1413 if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) { 1414 chain->status = get_equivalent_status_(status); 1415 cleanup_tempfile_(&tempfile, &tempfilename); 1416 return false; 1417 } 1418 if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) { 1419 chain->status = get_equivalent_status_(status); 1420 cleanup_tempfile_(&tempfile, &tempfilename); 1421 return false; 1422 } 1423 1424 /* write the metadata */ 1425 for(node = chain->head; node; node = node->next) { 1426 if(!write_metadata_block_header_(tempfile, &status, node->data)) { 1427 chain->status = get_equivalent_status_(status); 1428 return false; 1429 } 1430 if(!write_metadata_block_data_(tempfile, &status, node->data)) { 1431 chain->status = get_equivalent_status_(status); 1432 return false; 1433 } 1434 } 1435 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1436 1437 /* copy the file postfix (everything after the metadata) */ 1438 if(0 != fseeko(f, chain->last_offset, SEEK_SET)) { 1439 cleanup_tempfile_(&tempfile, &tempfilename); 1440 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1441 return false; 1442 } 1443 if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) { 1444 cleanup_tempfile_(&tempfile, &tempfilename); 1445 chain->status = get_equivalent_status_(status); 1446 return false; 1447 } 1448 1449 /* move the tempfile on top of the original */ 1450 (void)fclose(f); 1451 if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status)) 1452 return false; 1453 1454 return true; 1455 } 1456 1457 /* assumes 'handle' is already at beginning of file */ 1458 static FLAC__bool chain_rewrite_file_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb) 1459 { 1460 FLAC__Metadata_SimpleIteratorStatus status; 1461 const FLAC__Metadata_Node *node; 1462 1463 FLAC__ASSERT(0 != chain); 1464 FLAC__ASSERT(0 == chain->filename); 1465 FLAC__ASSERT(0 != chain->head); 1466 1467 /* copy the file prefix (data up to first metadata block */ 1468 if(!copy_n_bytes_from_file_cb_(handle, read_cb, temp_handle, temp_write_cb, chain->first_offset, &status)) { 1469 chain->status = get_equivalent_status_(status); 1470 return false; 1471 } 1472 1473 /* write the metadata */ 1474 for(node = chain->head; node; node = node->next) { 1475 if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) { 1476 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1477 return false; 1478 } 1479 if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) { 1480 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1481 return false; 1482 } 1483 } 1484 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1485 1486 /* copy the file postfix (everything after the metadata) */ 1487 if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) { 1488 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1489 return false; 1490 } 1491 if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) { 1492 chain->status = get_equivalent_status_(status); 1493 return false; 1494 } 1495 1496 return true; 1497 } 1498 1499 FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void) 1500 { 1501 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain)); 1502 1503 if(0 != chain) 1504 chain_init_(chain); 1505 1506 return chain; 1507 } 1508 1509 FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain) 1510 { 1511 FLAC__ASSERT(0 != chain); 1512 1513 chain_clear_(chain); 1514 1515 free(chain); 1516 } 1517 1518 FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain) 1519 { 1520 FLAC__Metadata_ChainStatus status; 1521 1522 FLAC__ASSERT(0 != chain); 1523 1524 status = chain->status; 1525 chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1526 return status; 1527 } 1528 1529 static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg) 1530 { 1531 FILE *file; 1532 FLAC__bool ret; 1533 1534 FLAC__ASSERT(0 != chain); 1535 FLAC__ASSERT(0 != filename); 1536 1537 chain_clear_(chain); 1538 1539 if(0 == (chain->filename = strdup(filename))) { 1540 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1541 return false; 1542 } 1543 1544 chain->is_ogg = is_ogg; 1545 1546 if(0 == (file = fopen(filename, "rb"))) { 1547 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1548 return false; 1549 } 1550 1551 /* the function also sets chain->status for us */ 1552 ret = is_ogg? 1553 chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) : 1554 chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_) 1555 ; 1556 1557 fclose(file); 1558 1559 return ret; 1560 } 1561 1562 FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename) 1563 { 1564 return chain_read_(chain, filename, /*is_ogg=*/false); 1565 } 1566 1567 /*@@@@add to tests*/ 1568 FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename) 1569 { 1570 return chain_read_(chain, filename, /*is_ogg=*/true); 1571 } 1572 1573 static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg) 1574 { 1575 FLAC__bool ret; 1576 1577 FLAC__ASSERT(0 != chain); 1578 1579 chain_clear_(chain); 1580 1581 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) { 1582 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1583 return false; 1584 } 1585 1586 chain->is_ogg = is_ogg; 1587 1588 /* rewind */ 1589 if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1590 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1591 return false; 1592 } 1593 1594 /* the function also sets chain->status for us */ 1595 ret = is_ogg? 1596 chain_read_ogg_cb_(chain, handle, callbacks.read) : 1597 chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell) 1598 ; 1599 1600 return ret; 1601 } 1602 1603 FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1604 { 1605 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false); 1606 } 1607 1608 /*@@@@add to tests*/ 1609 FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1610 { 1611 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true); 1612 } 1613 1614 FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) 1615 { 1616 /* This does all the same checks that are in chain_prepare_for_write_() 1617 * but doesn't actually alter the chain. Make sure to update the logic 1618 * here if chain_prepare_for_write_() changes. 1619 */ 1620 const off_t current_length = chain_calculate_length_(chain); 1621 1622 FLAC__ASSERT(0 != chain); 1623 1624 if(use_padding) { 1625 /* if the metadata shrank and the last block is padding, we just extend the last padding block */ 1626 if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) 1627 return false; 1628 /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ 1629 else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) 1630 return false; 1631 /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ 1632 else if(current_length > chain->initial_length) { 1633 const off_t delta = current_length - chain->initial_length; 1634 if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1635 /* if the delta is exactly the size of the last padding block, remove the padding block */ 1636 if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) 1637 return false; 1638 /* if there is at least 'delta' bytes of padding, trim the padding down */ 1639 else if((off_t)chain->tail->data->length >= delta) 1640 return false; 1641 } 1642 } 1643 } 1644 1645 return (current_length != chain->initial_length); 1646 } 1647 1648 FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats) 1649 { 1650 struct stat stats; 1651 const char *tempfile_path_prefix = 0; 1652 off_t current_length; 1653 1654 FLAC__ASSERT(0 != chain); 1655 1656 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1657 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1658 return false; 1659 } 1660 1661 if (0 == chain->filename) { 1662 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1663 return false; 1664 } 1665 1666 current_length = chain_prepare_for_write_(chain, use_padding); 1667 1668 /* a return value of 0 means there was an error; chain->status is already set */ 1669 if (0 == current_length) 1670 return false; 1671 1672 if(preserve_file_stats) 1673 get_file_stats_(chain->filename, &stats); 1674 1675 if(current_length == chain->initial_length) { 1676 if(!chain_rewrite_metadata_in_place_(chain)) 1677 return false; 1678 } 1679 else { 1680 if(!chain_rewrite_file_(chain, tempfile_path_prefix)) 1681 return false; 1682 1683 /* recompute lengths and offsets */ 1684 { 1685 const FLAC__Metadata_Node *node; 1686 chain->initial_length = current_length; 1687 chain->last_offset = chain->first_offset; 1688 for(node = chain->head; node; node = node->next) 1689 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1690 } 1691 } 1692 1693 if(preserve_file_stats) 1694 set_file_stats_(chain->filename, &stats); 1695 1696 return true; 1697 } 1698 1699 FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1700 { 1701 off_t current_length; 1702 1703 FLAC__ASSERT(0 != chain); 1704 1705 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1706 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1707 return false; 1708 } 1709 1710 if (0 != chain->filename) { 1711 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1712 return false; 1713 } 1714 1715 if (0 == callbacks.write || 0 == callbacks.seek) { 1716 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1717 return false; 1718 } 1719 1720 if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1721 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1722 return false; 1723 } 1724 1725 current_length = chain_prepare_for_write_(chain, use_padding); 1726 1727 /* a return value of 0 means there was an error; chain->status is already set */ 1728 if (0 == current_length) 1729 return false; 1730 1731 FLAC__ASSERT(current_length == chain->initial_length); 1732 1733 return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek); 1734 } 1735 1736 FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks) 1737 { 1738 off_t current_length; 1739 1740 FLAC__ASSERT(0 != chain); 1741 1742 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1743 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1744 return false; 1745 } 1746 1747 if (0 != chain->filename) { 1748 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1749 return false; 1750 } 1751 1752 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) { 1753 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1754 return false; 1755 } 1756 if (0 == temp_callbacks.write) { 1757 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1758 return false; 1759 } 1760 1761 if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1762 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1763 return false; 1764 } 1765 1766 current_length = chain_prepare_for_write_(chain, use_padding); 1767 1768 /* a return value of 0 means there was an error; chain->status is already set */ 1769 if (0 == current_length) 1770 return false; 1771 1772 FLAC__ASSERT(current_length != chain->initial_length); 1773 1774 /* rewind */ 1775 if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1776 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1777 return false; 1778 } 1779 1780 if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write)) 1781 return false; 1782 1783 /* recompute lengths and offsets */ 1784 { 1785 const FLAC__Metadata_Node *node; 1786 chain->initial_length = current_length; 1787 chain->last_offset = chain->first_offset; 1788 for(node = chain->head; node; node = node->next) 1789 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1790 } 1791 1792 return true; 1793 } 1794 1795 FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain) 1796 { 1797 FLAC__Metadata_Node *node; 1798 1799 FLAC__ASSERT(0 != chain); 1800 1801 for(node = chain->head; node; ) { 1802 if(!chain_merge_adjacent_padding_(chain, node)) 1803 node = node->next; 1804 } 1805 } 1806 1807 FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain) 1808 { 1809 FLAC__Metadata_Node *node, *save; 1810 unsigned i; 1811 1812 FLAC__ASSERT(0 != chain); 1813 1814 /* 1815 * Don't try and be too smart... this simple algo is good enough for 1816 * the small number of nodes that we deal with. 1817 */ 1818 for(i = 0, node = chain->head; i < chain->nodes; i++) { 1819 if(node->data->type == FLAC__METADATA_TYPE_PADDING) { 1820 save = node->next; 1821 chain_remove_node_(chain, node); 1822 chain_append_node_(chain, node); 1823 node = save; 1824 } 1825 else { 1826 node = node->next; 1827 } 1828 } 1829 1830 FLAC__metadata_chain_merge_padding(chain); 1831 } 1832 1833 1834 FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void) 1835 { 1836 FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator)); 1837 1838 /* calloc() implies: 1839 iterator->current = 0; 1840 iterator->chain = 0; 1841 */ 1842 1843 return iterator; 1844 } 1845 1846 FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator) 1847 { 1848 FLAC__ASSERT(0 != iterator); 1849 1850 free(iterator); 1851 } 1852 1853 FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain) 1854 { 1855 FLAC__ASSERT(0 != iterator); 1856 FLAC__ASSERT(0 != chain); 1857 FLAC__ASSERT(0 != chain->head); 1858 1859 iterator->chain = chain; 1860 iterator->current = chain->head; 1861 } 1862 1863 FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator) 1864 { 1865 FLAC__ASSERT(0 != iterator); 1866 1867 if(0 == iterator->current || 0 == iterator->current->next) 1868 return false; 1869 1870 iterator->current = iterator->current->next; 1871 return true; 1872 } 1873 1874 FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator) 1875 { 1876 FLAC__ASSERT(0 != iterator); 1877 1878 if(0 == iterator->current || 0 == iterator->current->prev) 1879 return false; 1880 1881 iterator->current = iterator->current->prev; 1882 return true; 1883 } 1884 1885 FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator) 1886 { 1887 FLAC__ASSERT(0 != iterator); 1888 FLAC__ASSERT(0 != iterator->current); 1889 FLAC__ASSERT(0 != iterator->current->data); 1890 1891 return iterator->current->data->type; 1892 } 1893 1894 FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator) 1895 { 1896 FLAC__ASSERT(0 != iterator); 1897 FLAC__ASSERT(0 != iterator->current); 1898 1899 return iterator->current->data; 1900 } 1901 1902 FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1903 { 1904 FLAC__ASSERT(0 != iterator); 1905 FLAC__ASSERT(0 != block); 1906 return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block); 1907 } 1908 1909 FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding) 1910 { 1911 FLAC__Metadata_Node *save; 1912 1913 FLAC__ASSERT(0 != iterator); 1914 FLAC__ASSERT(0 != iterator->current); 1915 1916 if(0 == iterator->current->prev) { 1917 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1918 return false; 1919 } 1920 1921 save = iterator->current->prev; 1922 1923 if(replace_with_padding) { 1924 FLAC__metadata_object_delete_data(iterator->current->data); 1925 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING; 1926 } 1927 else { 1928 chain_delete_node_(iterator->chain, iterator->current); 1929 } 1930 1931 iterator->current = save; 1932 return true; 1933 } 1934 1935 FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1936 { 1937 FLAC__Metadata_Node *node; 1938 1939 FLAC__ASSERT(0 != iterator); 1940 FLAC__ASSERT(0 != iterator->current); 1941 FLAC__ASSERT(0 != block); 1942 1943 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1944 return false; 1945 1946 if(0 == iterator->current->prev) { 1947 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1948 return false; 1949 } 1950 1951 if(0 == (node = node_new_())) 1952 return false; 1953 1954 node->data = block; 1955 iterator_insert_node_(iterator, node); 1956 iterator->current = node; 1957 return true; 1958 } 1959 1960 FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1961 { 1962 FLAC__Metadata_Node *node; 1963 1964 FLAC__ASSERT(0 != iterator); 1965 FLAC__ASSERT(0 != iterator->current); 1966 FLAC__ASSERT(0 != block); 1967 1968 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1969 return false; 1970 1971 if(0 == (node = node_new_())) 1972 return false; 1973 1974 node->data = block; 1975 iterator_insert_node_after_(iterator, node); 1976 iterator->current = node; 1977 return true; 1978 } 1979 1980 1981 /**************************************************************************** 1982 * 1983 * Local function definitions 1984 * 1985 ***************************************************************************/ 1986 1987 void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 1988 { 1989 unsigned i; 1990 1991 b += bytes; 1992 1993 for(i = 0; i < bytes; i++) { 1994 *(--b) = (FLAC__byte)(val & 0xff); 1995 val >>= 8; 1996 } 1997 } 1998 1999 void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 2000 { 2001 unsigned i; 2002 2003 for(i = 0; i < bytes; i++) { 2004 *(b++) = (FLAC__byte)(val & 0xff); 2005 val >>= 8; 2006 } 2007 } 2008 2009 void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes) 2010 { 2011 unsigned i; 2012 2013 b += bytes; 2014 2015 for(i = 0; i < bytes; i++) { 2016 *(--b) = (FLAC__byte)(val & 0xff); 2017 val >>= 8; 2018 } 2019 } 2020 2021 FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes) 2022 { 2023 FLAC__uint32 ret = 0; 2024 unsigned i; 2025 2026 for(i = 0; i < bytes; i++) 2027 ret = (ret << 8) | (FLAC__uint32)(*b++); 2028 2029 return ret; 2030 } 2031 2032 FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes) 2033 { 2034 FLAC__uint32 ret = 0; 2035 unsigned i; 2036 2037 b += bytes; 2038 2039 for(i = 0; i < bytes; i++) 2040 ret = (ret << 8) | (FLAC__uint32)(*--b); 2041 2042 return ret; 2043 } 2044 2045 FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes) 2046 { 2047 FLAC__uint64 ret = 0; 2048 unsigned i; 2049 2050 for(i = 0; i < bytes; i++) 2051 ret = (ret << 8) | (FLAC__uint64)(*b++); 2052 2053 return ret; 2054 } 2055 2056 FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) 2057 { 2058 FLAC__ASSERT(0 != iterator); 2059 FLAC__ASSERT(0 != iterator->file); 2060 2061 if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) { 2062 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2063 return false; 2064 } 2065 2066 return true; 2067 } 2068 2069 FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block) 2070 { 2071 FLAC__ASSERT(0 != iterator); 2072 FLAC__ASSERT(0 != iterator->file); 2073 2074 iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block); 2075 2076 return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK); 2077 } 2078 2079 FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length) 2080 { 2081 FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2082 2083 if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2084 return false; 2085 2086 *is_last = raw_header[0] & 0x80? true : false; 2087 *type = (FLAC__MetadataType)(raw_header[0] & 0x7f); 2088 *length = unpack_uint32_(raw_header + 1, 3); 2089 2090 /* Note that we don't check: 2091 * if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED) 2092 * we just will read in an opaque block 2093 */ 2094 2095 return true; 2096 } 2097 2098 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block) 2099 { 2100 switch(block->type) { 2101 case FLAC__METADATA_TYPE_STREAMINFO: 2102 return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info); 2103 case FLAC__METADATA_TYPE_PADDING: 2104 return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length); 2105 case FLAC__METADATA_TYPE_APPLICATION: 2106 return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length); 2107 case FLAC__METADATA_TYPE_SEEKTABLE: 2108 return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length); 2109 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2110 return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment); 2111 case FLAC__METADATA_TYPE_CUESHEET: 2112 return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet); 2113 case FLAC__METADATA_TYPE_PICTURE: 2114 return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture); 2115 default: 2116 return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length); 2117 } 2118 } 2119 2120 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block) 2121 { 2122 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b; 2123 2124 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2125 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2126 2127 b = buffer; 2128 2129 /* we are using hardcoded numbers for simplicity but we should 2130 * probably eventually write a bit-level unpacker and use the 2131 * _STREAMINFO_ constants. 2132 */ 2133 block->min_blocksize = unpack_uint32_(b, 2); b += 2; 2134 block->max_blocksize = unpack_uint32_(b, 2); b += 2; 2135 block->min_framesize = unpack_uint32_(b, 3); b += 3; 2136 block->max_framesize = unpack_uint32_(b, 3); b += 3; 2137 block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4); 2138 block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1; 2139 block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 4) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1; 2140 block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4); 2141 memcpy(block->md5sum, b+8, 16); 2142 2143 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2144 } 2145 2146 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length) 2147 { 2148 (void)block; /* nothing to do; we don't care about reading the padding bytes */ 2149 2150 if(0 != seek_cb(handle, block_length, SEEK_CUR)) 2151 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2152 2153 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2154 } 2155 2156 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length) 2157 { 2158 const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2159 2160 if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) 2161 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2162 2163 if(block_length < id_bytes) 2164 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2165 2166 block_length -= id_bytes; 2167 2168 if(block_length == 0) { 2169 block->data = 0; 2170 } 2171 else { 2172 if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2173 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2174 2175 if(read_cb(block->data, 1, block_length, handle) != block_length) 2176 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2177 } 2178 2179 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2180 } 2181 2182 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length) 2183 { 2184 unsigned i; 2185 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2186 2187 FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0); 2188 2189 block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; 2190 2191 if(block->num_points == 0) 2192 block->points = 0; 2193 else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) 2194 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2195 2196 for(i = 0; i < block->num_points; i++) { 2197 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2198 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2199 /* some MAGIC NUMBERs here */ 2200 block->points[i].sample_number = unpack_uint64_(buffer, 8); 2201 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8); 2202 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2); 2203 } 2204 2205 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2206 } 2207 2208 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry) 2209 { 2210 const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2211 FLAC__byte buffer[4]; /* magic number is asserted below */ 2212 2213 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer)); 2214 2215 if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2216 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2217 entry->length = unpack_uint32_little_endian_(buffer, entry_length_len); 2218 2219 if(0 != entry->entry) 2220 free(entry->entry); 2221 2222 if(entry->length == 0) { 2223 entry->entry = 0; 2224 } 2225 else { 2226 if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_2op_(entry->length, /*+*/1))) 2227 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2228 2229 if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) 2230 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2231 2232 entry->entry[entry->length] = '\0'; 2233 } 2234 2235 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2236 } 2237 2238 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block) 2239 { 2240 unsigned i; 2241 FLAC__Metadata_SimpleIteratorStatus status; 2242 const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2243 FLAC__byte buffer[4]; /* magic number is asserted below */ 2244 2245 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer)); 2246 2247 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string)))) 2248 return status; 2249 2250 if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2251 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2252 block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len); 2253 2254 if(block->num_comments == 0) { 2255 block->comments = 0; 2256 } 2257 else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) 2258 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2259 2260 for(i = 0; i < block->num_comments; i++) { 2261 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i))) 2262 return status; 2263 } 2264 2265 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2266 } 2267 2268 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track) 2269 { 2270 unsigned i, len; 2271 FLAC__byte buffer[32]; /* asserted below that this is big enough */ 2272 2273 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2274 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2275 FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8); 2276 2277 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2278 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2279 if(read_cb(buffer, 1, len, handle) != len) 2280 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2281 track->offset = unpack_uint64_(buffer, len); 2282 2283 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2284 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2285 if(read_cb(buffer, 1, len, handle) != len) 2286 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2287 track->number = (FLAC__byte)unpack_uint32_(buffer, len); 2288 2289 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2290 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2291 if(read_cb(track->isrc, 1, len, handle) != len) 2292 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2293 2294 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0); 2295 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2296 if(read_cb(buffer, 1, len, handle) != len) 2297 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2298 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1); 2299 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1); 2300 track->type = buffer[0] >> 7; 2301 track->pre_emphasis = (buffer[0] >> 6) & 1; 2302 2303 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2304 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2305 if(read_cb(buffer, 1, len, handle) != len) 2306 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2307 track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len); 2308 2309 if(track->num_indices == 0) { 2310 track->indices = 0; 2311 } 2312 else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) 2313 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2314 2315 for(i = 0; i < track->num_indices; i++) { 2316 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2317 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2318 if(read_cb(buffer, 1, len, handle) != len) 2319 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2320 track->indices[i].offset = unpack_uint64_(buffer, len); 2321 2322 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2323 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2324 if(read_cb(buffer, 1, len, handle) != len) 2325 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2326 track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len); 2327 2328 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2329 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2330 if(read_cb(buffer, 1, len, handle) != len) 2331 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2332 } 2333 2334 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2335 } 2336 2337 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block) 2338 { 2339 unsigned i, len; 2340 FLAC__Metadata_SimpleIteratorStatus status; 2341 FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */ 2342 2343 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer)); 2344 FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer)); 2345 2346 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2347 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2348 if(read_cb(block->media_catalog_number, 1, len, handle) != len) 2349 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2350 2351 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2352 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2353 if(read_cb(buffer, 1, len, handle) != len) 2354 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2355 block->lead_in = unpack_uint64_(buffer, len); 2356 2357 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2358 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2359 if(read_cb(buffer, 1, len, handle) != len) 2360 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2361 block->is_cd = buffer[0]&0x80? true : false; 2362 2363 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2364 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2365 if(read_cb(buffer, 1, len, handle) != len) 2366 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2367 block->num_tracks = unpack_uint32_(buffer, len); 2368 2369 if(block->num_tracks == 0) { 2370 block->tracks = 0; 2371 } 2372 else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) 2373 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2374 2375 for(i = 0; i < block->num_tracks; i++) { 2376 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i))) 2377 return status; 2378 } 2379 2380 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2381 } 2382 2383 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len) 2384 { 2385 FLAC__byte buffer[sizeof(FLAC__uint32)]; 2386 2387 FLAC__ASSERT(0 != data); 2388 FLAC__ASSERT(length_len%8 == 0); 2389 2390 length_len /= 8; /* convert to bytes */ 2391 2392 FLAC__ASSERT(sizeof(buffer) >= length_len); 2393 2394 if(read_cb(buffer, 1, length_len, handle) != length_len) 2395 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2396 *length = unpack_uint32_(buffer, length_len); 2397 2398 if(0 != *data) 2399 free(*data); 2400 2401 if(0 == (*data = (FLAC__byte*)safe_malloc_add_2op_(*length, /*+*/1))) 2402 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2403 2404 if(*length > 0) { 2405 if(read_cb(*data, 1, *length, handle) != *length) 2406 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2407 } 2408 2409 (*data)[*length] = '\0'; 2410 2411 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2412 } 2413 2414 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block) 2415 { 2416 FLAC__Metadata_SimpleIteratorStatus status; 2417 FLAC__byte buffer[4]; /* asserted below that this is big enough */ 2418 FLAC__uint32 len; 2419 2420 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2421 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2422 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2423 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2424 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2425 2426 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0); 2427 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8; 2428 if(read_cb(buffer, 1, len, handle) != len) 2429 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2430 block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len); 2431 2432 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2433 return status; 2434 2435 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2436 return status; 2437 2438 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0); 2439 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8; 2440 if(read_cb(buffer, 1, len, handle) != len) 2441 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2442 block->width = unpack_uint32_(buffer, len); 2443 2444 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0); 2445 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8; 2446 if(read_cb(buffer, 1, len, handle) != len) 2447 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2448 block->height = unpack_uint32_(buffer, len); 2449 2450 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0); 2451 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8; 2452 if(read_cb(buffer, 1, len, handle) != len) 2453 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2454 block->depth = unpack_uint32_(buffer, len); 2455 2456 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0); 2457 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8; 2458 if(read_cb(buffer, 1, len, handle) != len) 2459 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2460 block->colors = unpack_uint32_(buffer, len); 2461 2462 /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */ 2463 if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2464 return status; 2465 2466 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2467 } 2468 2469 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2470 { 2471 if(block_length == 0) { 2472 block->data = 0; 2473 } 2474 else { 2475 if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2476 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2477 2478 if(read_cb(block->data, 1, block_length, handle) != block_length) 2479 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2480 } 2481 2482 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2483 } 2484 2485 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2486 { 2487 FLAC__ASSERT(0 != file); 2488 FLAC__ASSERT(0 != status); 2489 2490 if(!write_metadata_block_header_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2491 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2492 return false; 2493 } 2494 2495 return true; 2496 } 2497 2498 FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2499 { 2500 FLAC__ASSERT(0 != file); 2501 FLAC__ASSERT(0 != status); 2502 2503 if (write_metadata_block_data_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2504 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2505 return true; 2506 } 2507 else { 2508 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2509 return false; 2510 } 2511 } 2512 2513 FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2514 { 2515 FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2516 2517 FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); 2518 2519 buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type; 2520 pack_uint32_(block->length, buffer + 1, 3); 2521 2522 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2523 return false; 2524 2525 return true; 2526 } 2527 2528 FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2529 { 2530 FLAC__ASSERT(0 != block); 2531 2532 switch(block->type) { 2533 case FLAC__METADATA_TYPE_STREAMINFO: 2534 return write_metadata_block_data_streaminfo_cb_(handle, write_cb, &block->data.stream_info); 2535 case FLAC__METADATA_TYPE_PADDING: 2536 return write_metadata_block_data_padding_cb_(handle, write_cb, &block->data.padding, block->length); 2537 case FLAC__METADATA_TYPE_APPLICATION: 2538 return write_metadata_block_data_application_cb_(handle, write_cb, &block->data.application, block->length); 2539 case FLAC__METADATA_TYPE_SEEKTABLE: 2540 return write_metadata_block_data_seektable_cb_(handle, write_cb, &block->data.seek_table); 2541 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2542 return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment); 2543 case FLAC__METADATA_TYPE_CUESHEET: 2544 return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet); 2545 case FLAC__METADATA_TYPE_PICTURE: 2546 return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture); 2547 default: 2548 return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length); 2549 } 2550 } 2551 2552 FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block) 2553 { 2554 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; 2555 const unsigned channels1 = block->channels - 1; 2556 const unsigned bps1 = block->bits_per_sample - 1; 2557 2558 /* we are using hardcoded numbers for simplicity but we should 2559 * probably eventually write a bit-level packer and use the 2560 * _STREAMINFO_ constants. 2561 */ 2562 pack_uint32_(block->min_blocksize, buffer, 2); 2563 pack_uint32_(block->max_blocksize, buffer+2, 2); 2564 pack_uint32_(block->min_framesize, buffer+4, 3); 2565 pack_uint32_(block->max_framesize, buffer+7, 3); 2566 buffer[10] = (block->sample_rate >> 12) & 0xff; 2567 buffer[11] = (block->sample_rate >> 4) & 0xff; 2568 buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4); 2569 buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f)); 2570 pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4); 2571 memcpy(buffer+18, block->md5sum, 16); 2572 2573 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2574 return false; 2575 2576 return true; 2577 } 2578 2579 FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length) 2580 { 2581 unsigned i, n = block_length; 2582 FLAC__byte buffer[1024]; 2583 2584 (void)block; 2585 2586 memset(buffer, 0, 1024); 2587 2588 for(i = 0; i < n/1024; i++) 2589 if(write_cb(buffer, 1, 1024, handle) != 1024) 2590 return false; 2591 2592 n %= 1024; 2593 2594 if(write_cb(buffer, 1, n, handle) != n) 2595 return false; 2596 2597 return true; 2598 } 2599 2600 FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length) 2601 { 2602 const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2603 2604 if(write_cb(block->id, 1, id_bytes, handle) != id_bytes) 2605 return false; 2606 2607 block_length -= id_bytes; 2608 2609 if(write_cb(block->data, 1, block_length, handle) != block_length) 2610 return false; 2611 2612 return true; 2613 } 2614 2615 FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block) 2616 { 2617 unsigned i; 2618 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2619 2620 for(i = 0; i < block->num_points; i++) { 2621 /* some MAGIC NUMBERs here */ 2622 pack_uint64_(block->points[i].sample_number, buffer, 8); 2623 pack_uint64_(block->points[i].stream_offset, buffer+8, 8); 2624 pack_uint32_(block->points[i].frame_samples, buffer+16, 2); 2625 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2626 return false; 2627 } 2628 2629 return true; 2630 } 2631 2632 FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block) 2633 { 2634 unsigned i; 2635 const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2636 const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2637 FLAC__byte buffer[4]; /* magic number is asserted below */ 2638 2639 FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer)); 2640 2641 pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len); 2642 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2643 return false; 2644 if(write_cb(block->vendor_string.entry, 1, block->vendor_string.length, handle) != block->vendor_string.length) 2645 return false; 2646 2647 pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len); 2648 if(write_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2649 return false; 2650 2651 for(i = 0; i < block->num_comments; i++) { 2652 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len); 2653 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2654 return false; 2655 if(write_cb(block->comments[i].entry, 1, block->comments[i].length, handle) != block->comments[i].length) 2656 return false; 2657 } 2658 2659 return true; 2660 } 2661 2662 FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block) 2663 { 2664 unsigned i, j, len; 2665 FLAC__byte buffer[1024]; /* asserted below that this is big enough */ 2666 2667 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2668 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN/8); 2669 FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)/8); 2670 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2671 2672 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2673 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2674 if(write_cb(block->media_catalog_number, 1, len, handle) != len) 2675 return false; 2676 2677 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2678 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2679 pack_uint64_(block->lead_in, buffer, len); 2680 if(write_cb(buffer, 1, len, handle) != len) 2681 return false; 2682 2683 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2684 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2685 memset(buffer, 0, len); 2686 if(block->is_cd) 2687 buffer[0] |= 0x80; 2688 if(write_cb(buffer, 1, len, handle) != len) 2689 return false; 2690 2691 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2692 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2693 pack_uint32_(block->num_tracks, buffer, len); 2694 if(write_cb(buffer, 1, len, handle) != len) 2695 return false; 2696 2697 for(i = 0; i < block->num_tracks; i++) { 2698 FLAC__StreamMetadata_CueSheet_Track *track = block->tracks + i; 2699 2700 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2701 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2702 pack_uint64_(track->offset, buffer, len); 2703 if(write_cb(buffer, 1, len, handle) != len) 2704 return false; 2705 2706 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2707 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2708 pack_uint32_(track->number, buffer, len); 2709 if(write_cb(buffer, 1, len, handle) != len) 2710 return false; 2711 2712 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2713 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2714 if(write_cb(track->isrc, 1, len, handle) != len) 2715 return false; 2716 2717 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0); 2718 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2719 memset(buffer, 0, len); 2720 buffer[0] = (track->type << 7) | (track->pre_emphasis << 6); 2721 if(write_cb(buffer, 1, len, handle) != len) 2722 return false; 2723 2724 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2725 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2726 pack_uint32_(track->num_indices, buffer, len); 2727 if(write_cb(buffer, 1, len, handle) != len) 2728 return false; 2729 2730 for(j = 0; j < track->num_indices; j++) { 2731 FLAC__StreamMetadata_CueSheet_Index *index = track->indices + j; 2732 2733 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2734 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2735 pack_uint64_(index->offset, buffer, len); 2736 if(write_cb(buffer, 1, len, handle) != len) 2737 return false; 2738 2739 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2740 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2741 pack_uint32_(index->number, buffer, len); 2742 if(write_cb(buffer, 1, len, handle) != len) 2743 return false; 2744 2745 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2746 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2747 memset(buffer, 0, len); 2748 if(write_cb(buffer, 1, len, handle) != len) 2749 return false; 2750 } 2751 } 2752 2753 return true; 2754 } 2755 2756 FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block) 2757 { 2758 unsigned len; 2759 size_t slen; 2760 FLAC__byte buffer[4]; /* magic number is asserted below */ 2761 2762 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8); 2763 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8); 2764 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8); 2765 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8); 2766 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8); 2767 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8); 2768 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8); 2769 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8); 2770 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2771 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8); 2772 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8); 2773 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2774 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2775 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2776 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2777 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8); 2778 2779 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8; 2780 pack_uint32_(block->type, buffer, len); 2781 if(write_cb(buffer, 1, len, handle) != len) 2782 return false; 2783 2784 len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8; 2785 slen = strlen(block->mime_type); 2786 pack_uint32_(slen, buffer, len); 2787 if(write_cb(buffer, 1, len, handle) != len) 2788 return false; 2789 if(write_cb(block->mime_type, 1, slen, handle) != slen) 2790 return false; 2791 2792 len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8; 2793 slen = strlen((const char *)block->description); 2794 pack_uint32_(slen, buffer, len); 2795 if(write_cb(buffer, 1, len, handle) != len) 2796 return false; 2797 if(write_cb(block->description, 1, slen, handle) != slen) 2798 return false; 2799 2800 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8; 2801 pack_uint32_(block->width, buffer, len); 2802 if(write_cb(buffer, 1, len, handle) != len) 2803 return false; 2804 2805 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8; 2806 pack_uint32_(block->height, buffer, len); 2807 if(write_cb(buffer, 1, len, handle) != len) 2808 return false; 2809 2810 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8; 2811 pack_uint32_(block->depth, buffer, len); 2812 if(write_cb(buffer, 1, len, handle) != len) 2813 return false; 2814 2815 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8; 2816 pack_uint32_(block->colors, buffer, len); 2817 if(write_cb(buffer, 1, len, handle) != len) 2818 return false; 2819 2820 len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8; 2821 pack_uint32_(block->data_length, buffer, len); 2822 if(write_cb(buffer, 1, len, handle) != len) 2823 return false; 2824 if(write_cb(block->data, 1, block->data_length, handle) != block->data_length) 2825 return false; 2826 2827 return true; 2828 } 2829 2830 FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2831 { 2832 if(write_cb(block->data, 1, block_length, handle) != block_length) 2833 return false; 2834 2835 return true; 2836 } 2837 2838 FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block) 2839 { 2840 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2841 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2842 return false; 2843 } 2844 2845 if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2846 return false; 2847 2848 if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2849 return false; 2850 2851 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2852 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2853 return false; 2854 } 2855 2856 return read_metadata_block_header_(iterator); 2857 } 2858 2859 FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last) 2860 { 2861 FLAC__StreamMetadata *padding; 2862 2863 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2864 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2865 return false; 2866 } 2867 2868 block->is_last = false; 2869 2870 if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2871 return false; 2872 2873 if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2874 return false; 2875 2876 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) 2877 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2878 2879 padding->is_last = padding_is_last; 2880 padding->length = padding_length; 2881 2882 if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) { 2883 FLAC__metadata_object_delete(padding); 2884 return false; 2885 } 2886 2887 if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) { 2888 FLAC__metadata_object_delete(padding); 2889 return false; 2890 } 2891 2892 FLAC__metadata_object_delete(padding); 2893 2894 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2895 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2896 return false; 2897 } 2898 2899 return read_metadata_block_header_(iterator); 2900 } 2901 2902 FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append) 2903 { 2904 FILE *tempfile; 2905 char *tempfilename; 2906 int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */ 2907 off_t fixup_is_last_flag_offset = -1; 2908 2909 FLAC__ASSERT(0 != block || append == false); 2910 2911 if(iterator->is_last) { 2912 if(append) { 2913 fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */ 2914 fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2915 } 2916 else if(0 == block) { 2917 simple_iterator_push_(iterator); 2918 if(!FLAC__metadata_simple_iterator_prev(iterator)) { 2919 (void)simple_iterator_pop_(iterator); 2920 return false; 2921 } 2922 fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */ 2923 fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2924 if(!simple_iterator_pop_(iterator)) 2925 return false; 2926 } 2927 } 2928 2929 if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append)) 2930 return false; 2931 2932 if(0 != block) { 2933 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) { 2934 cleanup_tempfile_(&tempfile, &tempfilename); 2935 return false; 2936 } 2937 2938 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) { 2939 cleanup_tempfile_(&tempfile, &tempfilename); 2940 return false; 2941 } 2942 } 2943 2944 if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0)) 2945 return false; 2946 2947 if(append) 2948 return FLAC__metadata_simple_iterator_next(iterator); 2949 2950 return true; 2951 } 2952 2953 void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator) 2954 { 2955 FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH); 2956 iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth]; 2957 iterator->depth++; 2958 } 2959 2960 FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator) 2961 { 2962 FLAC__ASSERT(iterator->depth > 0); 2963 iterator->depth--; 2964 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2965 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2966 return false; 2967 } 2968 2969 return read_metadata_block_header_(iterator); 2970 } 2971 2972 /* return meanings: 2973 * 0: ok 2974 * 1: read error 2975 * 2: seek error 2976 * 3: not a FLAC file 2977 */ 2978 unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb) 2979 { 2980 FLAC__byte buffer[4]; 2981 size_t n; 2982 unsigned i; 2983 2984 FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer)); 2985 2986 /* skip any id3v2 tag */ 2987 errno = 0; 2988 n = read_cb(buffer, 1, 4, handle); 2989 if(errno) 2990 return 1; 2991 else if(n != 4) 2992 return 3; 2993 else if(0 == memcmp(buffer, "ID3", 3)) { 2994 unsigned tag_length = 0; 2995 2996 /* skip to the tag length */ 2997 if(seek_cb(handle, 2, SEEK_CUR) < 0) 2998 return 2; 2999 3000 /* read the length */ 3001 for(i = 0; i < 4; i++) { 3002 if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80) 3003 return 1; 3004 tag_length <<= 7; 3005 tag_length |= (buffer[0] & 0x7f); 3006 } 3007 3008 /* skip the rest of the tag */ 3009 if(seek_cb(handle, tag_length, SEEK_CUR) < 0) 3010 return 2; 3011 3012 /* read the stream sync code */ 3013 errno = 0; 3014 n = read_cb(buffer, 1, 4, handle); 3015 if(errno) 3016 return 1; 3017 else if(n != 4) 3018 return 3; 3019 } 3020 3021 /* check for the fLaC signature */ 3022 if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH)) 3023 return 0; 3024 else 3025 return 3; 3026 } 3027 3028 unsigned seek_to_first_metadata_block_(FILE *f) 3029 { 3030 return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_); 3031 } 3032 3033 FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append) 3034 { 3035 const off_t offset_end = append? iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length : iterator->offset[iterator->depth]; 3036 3037 if(0 != fseeko(iterator->file, 0, SEEK_SET)) { 3038 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3039 return false; 3040 } 3041 if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) { 3042 cleanup_tempfile_(tempfile, tempfilename); 3043 return false; 3044 } 3045 if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) { 3046 cleanup_tempfile_(tempfile, tempfilename); 3047 return false; 3048 } 3049 3050 return true; 3051 } 3052 3053 FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup) 3054 { 3055 off_t save_offset = iterator->offset[iterator->depth]; 3056 FLAC__ASSERT(0 != *tempfile); 3057 3058 if(0 != fseeko(iterator->file, save_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length, SEEK_SET)) { 3059 cleanup_tempfile_(tempfile, tempfilename); 3060 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3061 return false; 3062 } 3063 if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) { 3064 cleanup_tempfile_(tempfile, tempfilename); 3065 return false; 3066 } 3067 3068 if(fixup_is_last_code != 0) { 3069 /* 3070 * if code == 1, it means a block was appended to the end so 3071 * we have to clear the is_last flag of the previous block 3072 * if code == -1, it means the last block was deleted so 3073 * we have to set the is_last flag of the previous block 3074 */ 3075 /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */ 3076 FLAC__byte x; 3077 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3078 cleanup_tempfile_(tempfile, tempfilename); 3079 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3080 return false; 3081 } 3082 if(fread(&x, 1, 1, *tempfile) != 1) { 3083 cleanup_tempfile_(tempfile, tempfilename); 3084 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3085 return false; 3086 } 3087 if(fixup_is_last_code > 0) { 3088 FLAC__ASSERT(x & 0x80); 3089 x &= 0x7f; 3090 } 3091 else { 3092 FLAC__ASSERT(!(x & 0x80)); 3093 x |= 0x80; 3094 } 3095 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3096 cleanup_tempfile_(tempfile, tempfilename); 3097 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3098 return false; 3099 } 3100 if(local__fwrite(&x, 1, 1, *tempfile) != 1) { 3101 cleanup_tempfile_(tempfile, tempfilename); 3102 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3103 return false; 3104 } 3105 } 3106 3107 (void)fclose(iterator->file); 3108 3109 if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status)) 3110 return false; 3111 3112 if(iterator->has_stats) 3113 set_file_stats_(iterator->filename, &iterator->stats); 3114 3115 if(!simple_iterator_prime_input_(iterator, !iterator->is_writable)) 3116 return false; 3117 if(backup) { 3118 while(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length < save_offset) 3119 if(!FLAC__metadata_simple_iterator_next(iterator)) 3120 return false; 3121 return true; 3122 } 3123 else { 3124 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */ 3125 FLAC__ASSERT(iterator->depth == 0); 3126 iterator->offset[0] = save_offset; 3127 iterator->depth++; 3128 return simple_iterator_pop_(iterator); 3129 } 3130 } 3131 3132 FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) 3133 { 3134 FLAC__byte buffer[8192]; 3135 size_t n; 3136 3137 FLAC__ASSERT(bytes >= 0); 3138 while(bytes > 0) { 3139 n = min(sizeof(buffer), (size_t)bytes); 3140 if(fread(buffer, 1, n, file) != n) { 3141 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3142 return false; 3143 } 3144 if(local__fwrite(buffer, 1, n, tempfile) != n) { 3145 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3146 return false; 3147 } 3148 bytes -= n; 3149 } 3150 3151 return true; 3152 } 3153 3154 FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) 3155 { 3156 FLAC__byte buffer[8192]; 3157 size_t n; 3158 3159 FLAC__ASSERT(bytes >= 0); 3160 while(bytes > 0) { 3161 n = min(sizeof(buffer), (size_t)bytes); 3162 if(read_cb(buffer, 1, n, handle) != n) { 3163 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3164 return false; 3165 } 3166 if(temp_write_cb(buffer, 1, n, temp_handle) != n) { 3167 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3168 return false; 3169 } 3170 bytes -= n; 3171 } 3172 3173 return true; 3174 } 3175 3176 FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status) 3177 { 3178 FLAC__byte buffer[8192]; 3179 size_t n; 3180 3181 while(!feof(file)) { 3182 n = fread(buffer, 1, sizeof(buffer), file); 3183 if(n == 0 && !feof(file)) { 3184 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3185 return false; 3186 } 3187 if(n > 0 && local__fwrite(buffer, 1, n, tempfile) != n) { 3188 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3189 return false; 3190 } 3191 } 3192 3193 return true; 3194 } 3195 3196 FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status) 3197 { 3198 FLAC__byte buffer[8192]; 3199 size_t n; 3200 3201 while(!eof_cb(handle)) { 3202 n = read_cb(buffer, 1, sizeof(buffer), handle); 3203 if(n == 0 && !eof_cb(handle)) { 3204 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3205 return false; 3206 } 3207 if(n > 0 && temp_write_cb(buffer, 1, n, temp_handle) != n) { 3208 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3209 return false; 3210 } 3211 } 3212 3213 return true; 3214 } 3215 3216 FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3217 { 3218 static const char *tempfile_suffix = ".metadata_edit"; 3219 if(0 == tempfile_path_prefix) { 3220 if(0 == (*tempfilename = (char*)safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) { 3221 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3222 return false; 3223 } 3224 strcpy(*tempfilename, filename); 3225 strcat(*tempfilename, tempfile_suffix); 3226 } 3227 else { 3228 const char *p = strrchr(filename, '/'); 3229 if(0 == p) 3230 p = filename; 3231 else 3232 p++; 3233 3234 if(0 == (*tempfilename = (char*)safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) { 3235 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3236 return false; 3237 } 3238 strcpy(*tempfilename, tempfile_path_prefix); 3239 strcat(*tempfilename, "/"); 3240 strcat(*tempfilename, p); 3241 strcat(*tempfilename, tempfile_suffix); 3242 } 3243 3244 if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) { 3245 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 3246 return false; 3247 } 3248 3249 return true; 3250 } 3251 3252 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3253 { 3254 FLAC__ASSERT(0 != filename); 3255 FLAC__ASSERT(0 != tempfile); 3256 FLAC__ASSERT(0 != *tempfile); 3257 FLAC__ASSERT(0 != tempfilename); 3258 FLAC__ASSERT(0 != *tempfilename); 3259 FLAC__ASSERT(0 != status); 3260 3261 (void)fclose(*tempfile); 3262 *tempfile = 0; 3263 3264 #if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__ 3265 /* on some flavors of windows, rename() will fail if the destination already exists */ 3266 if(unlink(filename) < 0) { 3267 cleanup_tempfile_(tempfile, tempfilename); 3268 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR; 3269 return false; 3270 } 3271 #endif 3272 3273 /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */ 3274 if(0 != rename(*tempfilename, filename)) { 3275 cleanup_tempfile_(tempfile, tempfilename); 3276 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR; 3277 return false; 3278 } 3279 3280 cleanup_tempfile_(tempfile, tempfilename); 3281 3282 return true; 3283 } 3284 3285 void cleanup_tempfile_(FILE **tempfile, char **tempfilename) 3286 { 3287 if(0 != *tempfile) { 3288 (void)fclose(*tempfile); 3289 *tempfile = 0; 3290 } 3291 3292 if(0 != *tempfilename) { 3293 (void)unlink(*tempfilename); 3294 free(*tempfilename); 3295 *tempfilename = 0; 3296 } 3297 } 3298 3299 FLAC__bool get_file_stats_(const char *filename, struct stat *stats) 3300 { 3301 FLAC__ASSERT(0 != filename); 3302 FLAC__ASSERT(0 != stats); 3303 return (0 == stat(filename, stats)); 3304 } 3305 3306 void set_file_stats_(const char *filename, struct stat *stats) 3307 { 3308 struct utimbuf srctime; 3309 3310 FLAC__ASSERT(0 != filename); 3311 FLAC__ASSERT(0 != stats); 3312 3313 srctime.actime = stats->st_atime; 3314 srctime.modtime = stats->st_mtime; 3315 (void)chmod(filename, stats->st_mode); 3316 (void)utime(filename, &srctime); 3317 #if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__ && !defined __EMX__ 3318 (void)chown(filename, stats->st_uid, -1); 3319 (void)chown(filename, -1, stats->st_gid); 3320 #endif 3321 } 3322 3323 int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence) 3324 { 3325 return fseeko((FILE*)handle, (off_t)offset, whence); 3326 } 3327 3328 FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle) 3329 { 3330 return ftello((FILE*)handle); 3331 } 3332 3333 FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status) 3334 { 3335 switch(status) { 3336 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK: 3337 return FLAC__METADATA_CHAIN_STATUS_OK; 3338 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: 3339 return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT; 3340 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: 3341 return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 3342 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: 3343 return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; 3344 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE: 3345 return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE; 3346 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA: 3347 return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA; 3348 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR: 3349 return FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 3350 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR: 3351 return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 3352 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR: 3353 return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 3354 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR: 3355 return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR; 3356 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR: 3357 return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR; 3358 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR: 3359 return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 3360 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR: 3361 default: 3362 return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 3363 } 3364 } 3365