metadata_iterators.c revision c74663799493f2b1e6123c18def94295d0afab7b
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 82static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 83static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 84static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes); 85static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes); 86static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes); 87static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes); 88 89static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator); 90static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block); 91static FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length); 92static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block); 93static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block); 94static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length); 95static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length); 96static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); 97static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry); 98static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block); 99static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track); 100static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block); 101static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block); 102static 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 104static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 105static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 106static FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 107static FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 108static FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block); 109static FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length); 110static FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length); 111static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block); 112static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block); 113static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block); 114static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block); 115static 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 117static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block); 118static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last); 119static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append); 120 121static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator); 122static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator); 123 124static unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb); 125static unsigned seek_to_first_metadata_block_(FILE *f); 126 127static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append); 128static 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 130static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); 131static 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); 132static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status); 133static 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 135static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 136static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 137static void cleanup_tempfile_(FILE **tempfile, char **tempfilename); 138 139static FLAC__bool get_file_stats_(const char *filename, struct stat *stats); 140static void set_file_stats_(const char *filename, struct stat *stats); 141 142static int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence); 143static FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle); 144 145static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status); 146 147 148#ifdef FLAC__VALGRIND_TESTING 149static 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 166static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); 167static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); 168static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); 169 170typedef struct { 171 FLAC__bool got_error; 172 FLAC__StreamMetadata *object; 173} level0_client_data; 174 175static 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 214FLAC_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 234FLAC_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 244FLAC_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 254FLAC__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 261void 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 276void 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 285FLAC_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 345struct 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 361FLAC_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 378FLAC_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 396static 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 416FLAC_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 424FLAC_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 435static 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 */ 494FLAC__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 497FLAC_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 521FLAC_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 529FLAC_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 547FLAC_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*/ 582FLAC_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*/ 591FLAC_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 599FLAC_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*/ 608FLAC_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*/ 617FLAC_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 644FLAC_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 673FLAC_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 771FLAC_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 850FLAC_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 895typedef struct FLAC__Metadata_Node { 896 FLAC__StreamMetadata *data; 897 struct FLAC__Metadata_Node *prev, *next; 898} FLAC__Metadata_Node; 899 900struct 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 919struct FLAC__Metadata_Iterator { 920 FLAC__Metadata_Chain *chain; 921 FLAC__Metadata_Node *current; 922}; 923 924FLAC_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 944static FLAC__Metadata_Node *node_new_(void) 945{ 946 return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node)); 947} 948 949static 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 957static 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 970static 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 988static 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 1010static 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 1031static 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 1037static 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 1046static 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 1071static 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 */ 1099static 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 */ 1119static 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 1173static 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 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1221 return false; 1222 } 1223 1224 node->data = FLAC__metadata_object_new(type); 1225 if(0 == node->data) { 1226 node_delete_(node); 1227 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1228 return false; 1229 } 1230 1231 node->data->is_last = is_last; 1232 node->data->length = length; 1233 1234 chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data)); 1235 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1236 node_delete_(node); 1237 return false; 1238 } 1239 chain_append_node_(chain, node); 1240 } while(!is_last); 1241 } 1242 1243 { 1244 FLAC__int64 pos = tell_cb(handle); 1245 if(pos < 0) { 1246 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1247 return false; 1248 } 1249 chain->last_offset = (off_t)pos; 1250 } 1251 1252 chain->initial_length = chain_calculate_length_(chain); 1253 1254 return true; 1255} 1256 1257static FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) 1258{ 1259 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1260 (void)decoder; 1261 if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) { 1262 *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle); 1263 if(*bytes == 0) 1264 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; 1265 else 1266 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 1267 } 1268 else 1269 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 1270} 1271 1272static FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) 1273{ 1274 (void)decoder, (void)frame, (void)buffer, (void)client_data; 1275 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; 1276} 1277 1278static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) 1279{ 1280 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1281 FLAC__Metadata_Node *node; 1282 1283 (void)decoder; 1284 1285 node = node_new_(); 1286 if(0 == node) { 1287 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1288 return; 1289 } 1290 1291 node->data = FLAC__metadata_object_clone(metadata); 1292 if(0 == node->data) { 1293 node_delete_(node); 1294 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1295 return; 1296 } 1297 1298 chain_append_node_(chain, node); 1299} 1300 1301static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 1302{ 1303 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1304 (void)decoder, (void)status; 1305 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1306} 1307 1308static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb) 1309{ 1310 FLAC__StreamDecoder *decoder; 1311 1312 FLAC__ASSERT(0 != chain); 1313 1314 /* we assume we're already at the beginning of the file */ 1315 1316 chain->handle = handle; 1317 chain->read_cb = read_cb; 1318 if(0 == (decoder = FLAC__stream_decoder_new())) { 1319 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1320 return false; 1321 } 1322 FLAC__stream_decoder_set_metadata_respond_all(decoder); 1323 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) { 1324 FLAC__stream_decoder_delete(decoder); 1325 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1326 return false; 1327 } 1328 1329 chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1330 1331 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) 1332 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1333 if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1334 FLAC__stream_decoder_delete(decoder); 1335 return false; 1336 } 1337 1338 FLAC__stream_decoder_delete(decoder); 1339 1340 chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1341 1342 chain->initial_length = chain_calculate_length_(chain); 1343 1344 return true; 1345} 1346 1347static 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) 1348{ 1349 FLAC__Metadata_Node *node; 1350 1351 FLAC__ASSERT(0 != chain); 1352 FLAC__ASSERT(0 != chain->head); 1353 1354 if(0 != seek_cb(handle, chain->first_offset, SEEK_SET)) { 1355 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1356 return false; 1357 } 1358 1359 for(node = chain->head; node; node = node->next) { 1360 if(!write_metadata_block_header_cb_(handle, write_cb, node->data)) { 1361 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1362 return false; 1363 } 1364 if(!write_metadata_block_data_cb_(handle, write_cb, node->data)) { 1365 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1366 return false; 1367 } 1368 } 1369 1370 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1371 1372 chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1373 return true; 1374} 1375 1376static FLAC__bool chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain *chain) 1377{ 1378 FILE *file; 1379 FLAC__bool ret; 1380 1381 FLAC__ASSERT(0 != chain->filename); 1382 1383 if(0 == (file = fopen(chain->filename, "r+b"))) { 1384 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1385 return false; 1386 } 1387 1388 /* chain_rewrite_metadata_in_place_cb_() sets chain->status for us */ 1389 ret = chain_rewrite_metadata_in_place_cb_(chain, (FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, fseek_wrapper_); 1390 1391 fclose(file); 1392 1393 return ret; 1394} 1395 1396static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix) 1397{ 1398 FILE *f, *tempfile; 1399 char *tempfilename; 1400 FLAC__Metadata_SimpleIteratorStatus status; 1401 const FLAC__Metadata_Node *node; 1402 1403 FLAC__ASSERT(0 != chain); 1404 FLAC__ASSERT(0 != chain->filename); 1405 FLAC__ASSERT(0 != chain->head); 1406 1407 /* copy the file prefix (data up to first metadata block */ 1408 if(0 == (f = fopen(chain->filename, "rb"))) { 1409 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1410 return false; 1411 } 1412 if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) { 1413 chain->status = get_equivalent_status_(status); 1414 cleanup_tempfile_(&tempfile, &tempfilename); 1415 return false; 1416 } 1417 if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) { 1418 chain->status = get_equivalent_status_(status); 1419 cleanup_tempfile_(&tempfile, &tempfilename); 1420 return false; 1421 } 1422 1423 /* write the metadata */ 1424 for(node = chain->head; node; node = node->next) { 1425 if(!write_metadata_block_header_(tempfile, &status, node->data)) { 1426 chain->status = get_equivalent_status_(status); 1427 return false; 1428 } 1429 if(!write_metadata_block_data_(tempfile, &status, node->data)) { 1430 chain->status = get_equivalent_status_(status); 1431 return false; 1432 } 1433 } 1434 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1435 1436 /* copy the file postfix (everything after the metadata) */ 1437 if(0 != fseeko(f, chain->last_offset, SEEK_SET)) { 1438 cleanup_tempfile_(&tempfile, &tempfilename); 1439 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1440 return false; 1441 } 1442 if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) { 1443 cleanup_tempfile_(&tempfile, &tempfilename); 1444 chain->status = get_equivalent_status_(status); 1445 return false; 1446 } 1447 1448 /* move the tempfile on top of the original */ 1449 (void)fclose(f); 1450 if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status)) 1451 return false; 1452 1453 return true; 1454} 1455 1456/* assumes 'handle' is already at beginning of file */ 1457static 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) 1458{ 1459 FLAC__Metadata_SimpleIteratorStatus status; 1460 const FLAC__Metadata_Node *node; 1461 1462 FLAC__ASSERT(0 != chain); 1463 FLAC__ASSERT(0 == chain->filename); 1464 FLAC__ASSERT(0 != chain->head); 1465 1466 /* copy the file prefix (data up to first metadata block */ 1467 if(!copy_n_bytes_from_file_cb_(handle, read_cb, temp_handle, temp_write_cb, chain->first_offset, &status)) { 1468 chain->status = get_equivalent_status_(status); 1469 return false; 1470 } 1471 1472 /* write the metadata */ 1473 for(node = chain->head; node; node = node->next) { 1474 if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) { 1475 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1476 return false; 1477 } 1478 if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) { 1479 chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1480 return false; 1481 } 1482 } 1483 /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1484 1485 /* copy the file postfix (everything after the metadata) */ 1486 if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) { 1487 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1488 return false; 1489 } 1490 if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) { 1491 chain->status = get_equivalent_status_(status); 1492 return false; 1493 } 1494 1495 return true; 1496} 1497 1498FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void) 1499{ 1500 FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain)); 1501 1502 if(0 != chain) 1503 chain_init_(chain); 1504 1505 return chain; 1506} 1507 1508FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain) 1509{ 1510 FLAC__ASSERT(0 != chain); 1511 1512 chain_clear_(chain); 1513 1514 free(chain); 1515} 1516 1517FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain) 1518{ 1519 FLAC__Metadata_ChainStatus status; 1520 1521 FLAC__ASSERT(0 != chain); 1522 1523 status = chain->status; 1524 chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1525 return status; 1526} 1527 1528static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg) 1529{ 1530 FILE *file; 1531 FLAC__bool ret; 1532 1533 FLAC__ASSERT(0 != chain); 1534 FLAC__ASSERT(0 != filename); 1535 1536 chain_clear_(chain); 1537 1538 if(0 == (chain->filename = strdup(filename))) { 1539 chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1540 return false; 1541 } 1542 1543 chain->is_ogg = is_ogg; 1544 1545 if(0 == (file = fopen(filename, "rb"))) { 1546 chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1547 return false; 1548 } 1549 1550 /* the function also sets chain->status for us */ 1551 ret = is_ogg? 1552 chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) : 1553 chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_) 1554 ; 1555 1556 fclose(file); 1557 1558 return ret; 1559} 1560 1561FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename) 1562{ 1563 return chain_read_(chain, filename, /*is_ogg=*/false); 1564} 1565 1566/*@@@@add to tests*/ 1567FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename) 1568{ 1569 return chain_read_(chain, filename, /*is_ogg=*/true); 1570} 1571 1572static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg) 1573{ 1574 FLAC__bool ret; 1575 1576 FLAC__ASSERT(0 != chain); 1577 1578 chain_clear_(chain); 1579 1580 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) { 1581 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1582 return false; 1583 } 1584 1585 chain->is_ogg = is_ogg; 1586 1587 /* rewind */ 1588 if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1589 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1590 return false; 1591 } 1592 1593 /* the function also sets chain->status for us */ 1594 ret = is_ogg? 1595 chain_read_ogg_cb_(chain, handle, callbacks.read) : 1596 chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell) 1597 ; 1598 1599 return ret; 1600} 1601 1602FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1603{ 1604 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false); 1605} 1606 1607/*@@@@add to tests*/ 1608FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1609{ 1610 return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true); 1611} 1612 1613FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) 1614{ 1615 /* This does all the same checks that are in chain_prepare_for_write_() 1616 * but doesn't actually alter the chain. Make sure to update the logic 1617 * here if chain_prepare_for_write_() changes. 1618 */ 1619 const off_t current_length = chain_calculate_length_(chain); 1620 1621 FLAC__ASSERT(0 != chain); 1622 1623 if(use_padding) { 1624 /* if the metadata shrank and the last block is padding, we just extend the last padding block */ 1625 if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) 1626 return false; 1627 /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ 1628 else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) 1629 return false; 1630 /* 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 */ 1631 else if(current_length > chain->initial_length) { 1632 const off_t delta = current_length - chain->initial_length; 1633 if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1634 /* if the delta is exactly the size of the last padding block, remove the padding block */ 1635 if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) 1636 return false; 1637 /* if there is at least 'delta' bytes of padding, trim the padding down */ 1638 else if((off_t)chain->tail->data->length >= delta) 1639 return false; 1640 } 1641 } 1642 } 1643 1644 return (current_length != chain->initial_length); 1645} 1646 1647FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats) 1648{ 1649 struct stat stats; 1650 const char *tempfile_path_prefix = 0; 1651 off_t current_length; 1652 1653 FLAC__ASSERT(0 != chain); 1654 1655 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1656 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1657 return false; 1658 } 1659 1660 if (0 == chain->filename) { 1661 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1662 return false; 1663 } 1664 1665 current_length = chain_prepare_for_write_(chain, use_padding); 1666 1667 /* a return value of 0 means there was an error; chain->status is already set */ 1668 if (0 == current_length) 1669 return false; 1670 1671 if(preserve_file_stats) 1672 get_file_stats_(chain->filename, &stats); 1673 1674 if(current_length == chain->initial_length) { 1675 if(!chain_rewrite_metadata_in_place_(chain)) 1676 return false; 1677 } 1678 else { 1679 if(!chain_rewrite_file_(chain, tempfile_path_prefix)) 1680 return false; 1681 1682 /* recompute lengths and offsets */ 1683 { 1684 const FLAC__Metadata_Node *node; 1685 chain->initial_length = current_length; 1686 chain->last_offset = chain->first_offset; 1687 for(node = chain->head; node; node = node->next) 1688 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1689 } 1690 } 1691 1692 if(preserve_file_stats) 1693 set_file_stats_(chain->filename, &stats); 1694 1695 return true; 1696} 1697 1698FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1699{ 1700 off_t current_length; 1701 1702 FLAC__ASSERT(0 != chain); 1703 1704 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1705 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1706 return false; 1707 } 1708 1709 if (0 != chain->filename) { 1710 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1711 return false; 1712 } 1713 1714 if (0 == callbacks.write || 0 == callbacks.seek) { 1715 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1716 return false; 1717 } 1718 1719 if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1720 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1721 return false; 1722 } 1723 1724 current_length = chain_prepare_for_write_(chain, use_padding); 1725 1726 /* a return value of 0 means there was an error; chain->status is already set */ 1727 if (0 == current_length) 1728 return false; 1729 1730 FLAC__ASSERT(current_length == chain->initial_length); 1731 1732 return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek); 1733} 1734 1735FLAC_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) 1736{ 1737 off_t current_length; 1738 1739 FLAC__ASSERT(0 != chain); 1740 1741 if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1742 chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1743 return false; 1744 } 1745 1746 if (0 != chain->filename) { 1747 chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1748 return false; 1749 } 1750 1751 if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) { 1752 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1753 return false; 1754 } 1755 if (0 == temp_callbacks.write) { 1756 chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1757 return false; 1758 } 1759 1760 if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1761 chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1762 return false; 1763 } 1764 1765 current_length = chain_prepare_for_write_(chain, use_padding); 1766 1767 /* a return value of 0 means there was an error; chain->status is already set */ 1768 if (0 == current_length) 1769 return false; 1770 1771 FLAC__ASSERT(current_length != chain->initial_length); 1772 1773 /* rewind */ 1774 if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1775 chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1776 return false; 1777 } 1778 1779 if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write)) 1780 return false; 1781 1782 /* recompute lengths and offsets */ 1783 { 1784 const FLAC__Metadata_Node *node; 1785 chain->initial_length = current_length; 1786 chain->last_offset = chain->first_offset; 1787 for(node = chain->head; node; node = node->next) 1788 chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1789 } 1790 1791 return true; 1792} 1793 1794FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain) 1795{ 1796 FLAC__Metadata_Node *node; 1797 1798 FLAC__ASSERT(0 != chain); 1799 1800 for(node = chain->head; node; ) { 1801 if(!chain_merge_adjacent_padding_(chain, node)) 1802 node = node->next; 1803 } 1804} 1805 1806FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain) 1807{ 1808 FLAC__Metadata_Node *node, *save; 1809 unsigned i; 1810 1811 FLAC__ASSERT(0 != chain); 1812 1813 /* 1814 * Don't try and be too smart... this simple algo is good enough for 1815 * the small number of nodes that we deal with. 1816 */ 1817 for(i = 0, node = chain->head; i < chain->nodes; i++) { 1818 if(node->data->type == FLAC__METADATA_TYPE_PADDING) { 1819 save = node->next; 1820 chain_remove_node_(chain, node); 1821 chain_append_node_(chain, node); 1822 node = save; 1823 } 1824 else { 1825 node = node->next; 1826 } 1827 } 1828 1829 FLAC__metadata_chain_merge_padding(chain); 1830} 1831 1832 1833FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void) 1834{ 1835 FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator)); 1836 1837 /* calloc() implies: 1838 iterator->current = 0; 1839 iterator->chain = 0; 1840 */ 1841 1842 return iterator; 1843} 1844 1845FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator) 1846{ 1847 FLAC__ASSERT(0 != iterator); 1848 1849 free(iterator); 1850} 1851 1852FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain) 1853{ 1854 FLAC__ASSERT(0 != iterator); 1855 FLAC__ASSERT(0 != chain); 1856 FLAC__ASSERT(0 != chain->head); 1857 1858 iterator->chain = chain; 1859 iterator->current = chain->head; 1860} 1861 1862FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator) 1863{ 1864 FLAC__ASSERT(0 != iterator); 1865 1866 if(0 == iterator->current || 0 == iterator->current->next) 1867 return false; 1868 1869 iterator->current = iterator->current->next; 1870 return true; 1871} 1872 1873FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator) 1874{ 1875 FLAC__ASSERT(0 != iterator); 1876 1877 if(0 == iterator->current || 0 == iterator->current->prev) 1878 return false; 1879 1880 iterator->current = iterator->current->prev; 1881 return true; 1882} 1883 1884FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator) 1885{ 1886 FLAC__ASSERT(0 != iterator); 1887 FLAC__ASSERT(0 != iterator->current); 1888 FLAC__ASSERT(0 != iterator->current->data); 1889 1890 return iterator->current->data->type; 1891} 1892 1893FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator) 1894{ 1895 FLAC__ASSERT(0 != iterator); 1896 FLAC__ASSERT(0 != iterator->current); 1897 1898 return iterator->current->data; 1899} 1900 1901FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1902{ 1903 FLAC__ASSERT(0 != iterator); 1904 FLAC__ASSERT(0 != block); 1905 return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block); 1906} 1907 1908FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding) 1909{ 1910 FLAC__Metadata_Node *save; 1911 1912 FLAC__ASSERT(0 != iterator); 1913 FLAC__ASSERT(0 != iterator->current); 1914 1915 if(0 == iterator->current->prev) { 1916 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1917 return false; 1918 } 1919 1920 save = iterator->current->prev; 1921 1922 if(replace_with_padding) { 1923 FLAC__metadata_object_delete_data(iterator->current->data); 1924 iterator->current->data->type = FLAC__METADATA_TYPE_PADDING; 1925 } 1926 else { 1927 chain_delete_node_(iterator->chain, iterator->current); 1928 } 1929 1930 iterator->current = save; 1931 return true; 1932} 1933 1934FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1935{ 1936 FLAC__Metadata_Node *node; 1937 1938 FLAC__ASSERT(0 != iterator); 1939 FLAC__ASSERT(0 != iterator->current); 1940 FLAC__ASSERT(0 != block); 1941 1942 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1943 return false; 1944 1945 if(0 == iterator->current->prev) { 1946 FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1947 return false; 1948 } 1949 1950 if(0 == (node = node_new_())) 1951 return false; 1952 1953 node->data = block; 1954 iterator_insert_node_(iterator, node); 1955 iterator->current = node; 1956 return true; 1957} 1958 1959FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1960{ 1961 FLAC__Metadata_Node *node; 1962 1963 FLAC__ASSERT(0 != iterator); 1964 FLAC__ASSERT(0 != iterator->current); 1965 FLAC__ASSERT(0 != block); 1966 1967 if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1968 return false; 1969 1970 if(0 == (node = node_new_())) 1971 return false; 1972 1973 node->data = block; 1974 iterator_insert_node_after_(iterator, node); 1975 iterator->current = node; 1976 return true; 1977} 1978 1979 1980/**************************************************************************** 1981 * 1982 * Local function definitions 1983 * 1984 ***************************************************************************/ 1985 1986void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 1987{ 1988 unsigned i; 1989 1990 b += bytes; 1991 1992 for(i = 0; i < bytes; i++) { 1993 *(--b) = (FLAC__byte)(val & 0xff); 1994 val >>= 8; 1995 } 1996} 1997 1998void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 1999{ 2000 unsigned i; 2001 2002 for(i = 0; i < bytes; i++) { 2003 *(b++) = (FLAC__byte)(val & 0xff); 2004 val >>= 8; 2005 } 2006} 2007 2008void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes) 2009{ 2010 unsigned i; 2011 2012 b += bytes; 2013 2014 for(i = 0; i < bytes; i++) { 2015 *(--b) = (FLAC__byte)(val & 0xff); 2016 val >>= 8; 2017 } 2018} 2019 2020FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes) 2021{ 2022 FLAC__uint32 ret = 0; 2023 unsigned i; 2024 2025 for(i = 0; i < bytes; i++) 2026 ret = (ret << 8) | (FLAC__uint32)(*b++); 2027 2028 return ret; 2029} 2030 2031FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes) 2032{ 2033 FLAC__uint32 ret = 0; 2034 unsigned i; 2035 2036 b += bytes; 2037 2038 for(i = 0; i < bytes; i++) 2039 ret = (ret << 8) | (FLAC__uint32)(*--b); 2040 2041 return ret; 2042} 2043 2044FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes) 2045{ 2046 FLAC__uint64 ret = 0; 2047 unsigned i; 2048 2049 for(i = 0; i < bytes; i++) 2050 ret = (ret << 8) | (FLAC__uint64)(*b++); 2051 2052 return ret; 2053} 2054 2055FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) 2056{ 2057 FLAC__ASSERT(0 != iterator); 2058 FLAC__ASSERT(0 != iterator->file); 2059 2060 if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) { 2061 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2062 return false; 2063 } 2064 2065 return true; 2066} 2067 2068FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block) 2069{ 2070 FLAC__ASSERT(0 != iterator); 2071 FLAC__ASSERT(0 != iterator->file); 2072 2073 iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block); 2074 2075 return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK); 2076} 2077 2078FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length) 2079{ 2080 FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2081 2082 if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2083 return false; 2084 2085 *is_last = raw_header[0] & 0x80? true : false; 2086 *type = (FLAC__MetadataType)(raw_header[0] & 0x7f); 2087 *length = unpack_uint32_(raw_header + 1, 3); 2088 2089 /* Note that we don't check: 2090 * if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED) 2091 * we just will read in an opaque block 2092 */ 2093 2094 return true; 2095} 2096 2097FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block) 2098{ 2099 switch(block->type) { 2100 case FLAC__METADATA_TYPE_STREAMINFO: 2101 return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info); 2102 case FLAC__METADATA_TYPE_PADDING: 2103 return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length); 2104 case FLAC__METADATA_TYPE_APPLICATION: 2105 return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length); 2106 case FLAC__METADATA_TYPE_SEEKTABLE: 2107 return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length); 2108 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2109 return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment); 2110 case FLAC__METADATA_TYPE_CUESHEET: 2111 return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet); 2112 case FLAC__METADATA_TYPE_PICTURE: 2113 return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture); 2114 default: 2115 return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length); 2116 } 2117} 2118 2119FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block) 2120{ 2121 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b; 2122 2123 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2124 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2125 2126 b = buffer; 2127 2128 /* we are using hardcoded numbers for simplicity but we should 2129 * probably eventually write a bit-level unpacker and use the 2130 * _STREAMINFO_ constants. 2131 */ 2132 block->min_blocksize = unpack_uint32_(b, 2); b += 2; 2133 block->max_blocksize = unpack_uint32_(b, 2); b += 2; 2134 block->min_framesize = unpack_uint32_(b, 3); b += 3; 2135 block->max_framesize = unpack_uint32_(b, 3); b += 3; 2136 block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4); 2137 block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1; 2138 block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 4) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1; 2139 block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4); 2140 memcpy(block->md5sum, b+8, 16); 2141 2142 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2143} 2144 2145FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length) 2146{ 2147 (void)block; /* nothing to do; we don't care about reading the padding bytes */ 2148 2149 if(0 != seek_cb(handle, block_length, SEEK_CUR)) 2150 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2151 2152 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2153} 2154 2155FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length) 2156{ 2157 const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2158 2159 if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) 2160 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2161 2162 if(block_length < id_bytes) 2163 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2164 2165 block_length -= id_bytes; 2166 2167 if(block_length == 0) { 2168 block->data = 0; 2169 } 2170 else { 2171 if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2172 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2173 2174 if(read_cb(block->data, 1, block_length, handle) != block_length) 2175 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2176 } 2177 2178 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2179} 2180 2181FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length) 2182{ 2183 unsigned i; 2184 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2185 2186 FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0); 2187 2188 block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; 2189 2190 if(block->num_points == 0) 2191 block->points = 0; 2192 else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) 2193 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2194 2195 for(i = 0; i < block->num_points; i++) { 2196 if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2197 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2198 /* some MAGIC NUMBERs here */ 2199 block->points[i].sample_number = unpack_uint64_(buffer, 8); 2200 block->points[i].stream_offset = unpack_uint64_(buffer+8, 8); 2201 block->points[i].frame_samples = unpack_uint32_(buffer+16, 2); 2202 } 2203 2204 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2205} 2206 2207FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry) 2208{ 2209 const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2210 FLAC__byte buffer[4]; /* magic number is asserted below */ 2211 2212 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer)); 2213 2214 if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2215 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2216 entry->length = unpack_uint32_little_endian_(buffer, entry_length_len); 2217 2218 if(0 != entry->entry) 2219 free(entry->entry); 2220 2221 if(entry->length == 0) { 2222 entry->entry = 0; 2223 } 2224 else { 2225 if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_2op_(entry->length, /*+*/1))) 2226 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2227 2228 if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) 2229 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2230 2231 entry->entry[entry->length] = '\0'; 2232 } 2233 2234 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2235} 2236 2237FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block) 2238{ 2239 unsigned i; 2240 FLAC__Metadata_SimpleIteratorStatus status; 2241 const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2242 FLAC__byte buffer[4]; /* magic number is asserted below */ 2243 2244 FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer)); 2245 2246 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string)))) 2247 return status; 2248 2249 if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2250 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2251 block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len); 2252 2253 if(block->num_comments == 0) { 2254 block->comments = 0; 2255 } 2256 else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) 2257 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2258 2259 for(i = 0; i < block->num_comments; i++) { 2260 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i))) 2261 return status; 2262 } 2263 2264 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2265} 2266 2267FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track) 2268{ 2269 unsigned i, len; 2270 FLAC__byte buffer[32]; /* asserted below that this is big enough */ 2271 2272 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2273 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2274 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); 2275 2276 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2277 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2278 if(read_cb(buffer, 1, len, handle) != len) 2279 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2280 track->offset = unpack_uint64_(buffer, len); 2281 2282 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2283 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2284 if(read_cb(buffer, 1, len, handle) != len) 2285 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2286 track->number = (FLAC__byte)unpack_uint32_(buffer, len); 2287 2288 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2289 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2290 if(read_cb(track->isrc, 1, len, handle) != len) 2291 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2292 2293 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); 2294 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2295 if(read_cb(buffer, 1, len, handle) != len) 2296 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2297 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1); 2298 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1); 2299 track->type = buffer[0] >> 7; 2300 track->pre_emphasis = (buffer[0] >> 6) & 1; 2301 2302 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2303 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2304 if(read_cb(buffer, 1, len, handle) != len) 2305 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2306 track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len); 2307 2308 if(track->num_indices == 0) { 2309 track->indices = 0; 2310 } 2311 else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) 2312 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2313 2314 for(i = 0; i < track->num_indices; i++) { 2315 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2316 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2317 if(read_cb(buffer, 1, len, handle) != len) 2318 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2319 track->indices[i].offset = unpack_uint64_(buffer, len); 2320 2321 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2322 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2323 if(read_cb(buffer, 1, len, handle) != len) 2324 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2325 track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len); 2326 2327 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2328 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2329 if(read_cb(buffer, 1, len, handle) != len) 2330 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2331 } 2332 2333 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2334} 2335 2336FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block) 2337{ 2338 unsigned i, len; 2339 FLAC__Metadata_SimpleIteratorStatus status; 2340 FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */ 2341 2342 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer)); 2343 FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer)); 2344 2345 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2346 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2347 if(read_cb(block->media_catalog_number, 1, len, handle) != len) 2348 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2349 2350 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2351 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2352 if(read_cb(buffer, 1, len, handle) != len) 2353 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2354 block->lead_in = unpack_uint64_(buffer, len); 2355 2356 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2357 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2358 if(read_cb(buffer, 1, len, handle) != len) 2359 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2360 block->is_cd = buffer[0]&0x80? true : false; 2361 2362 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2363 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2364 if(read_cb(buffer, 1, len, handle) != len) 2365 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2366 block->num_tracks = unpack_uint32_(buffer, len); 2367 2368 if(block->num_tracks == 0) { 2369 block->tracks = 0; 2370 } 2371 else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) 2372 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2373 2374 for(i = 0; i < block->num_tracks; i++) { 2375 if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i))) 2376 return status; 2377 } 2378 2379 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2380} 2381 2382static 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) 2383{ 2384 FLAC__byte buffer[sizeof(FLAC__uint32)]; 2385 2386 FLAC__ASSERT(0 != data); 2387 FLAC__ASSERT(length_len%8 == 0); 2388 2389 length_len /= 8; /* convert to bytes */ 2390 2391 FLAC__ASSERT(sizeof(buffer) >= length_len); 2392 2393 if(read_cb(buffer, 1, length_len, handle) != length_len) 2394 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2395 *length = unpack_uint32_(buffer, length_len); 2396 2397 if(0 != *data) 2398 free(*data); 2399 2400 if(0 == (*data = (FLAC__byte*)safe_malloc_add_2op_(*length, /*+*/1))) 2401 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2402 2403 if(*length > 0) { 2404 if(read_cb(*data, 1, *length, handle) != *length) 2405 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2406 } 2407 2408 (*data)[*length] = '\0'; 2409 2410 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2411} 2412 2413FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block) 2414{ 2415 FLAC__Metadata_SimpleIteratorStatus status; 2416 FLAC__byte buffer[4]; /* asserted below that this is big enough */ 2417 FLAC__uint32 len; 2418 2419 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2420 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2421 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2422 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2423 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2424 2425 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0); 2426 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8; 2427 if(read_cb(buffer, 1, len, handle) != len) 2428 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2429 block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len); 2430 2431 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) 2432 return status; 2433 2434 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) 2435 return status; 2436 2437 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0); 2438 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8; 2439 if(read_cb(buffer, 1, len, handle) != len) 2440 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2441 block->width = unpack_uint32_(buffer, len); 2442 2443 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0); 2444 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8; 2445 if(read_cb(buffer, 1, len, handle) != len) 2446 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2447 block->height = unpack_uint32_(buffer, len); 2448 2449 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0); 2450 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8; 2451 if(read_cb(buffer, 1, len, handle) != len) 2452 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2453 block->depth = unpack_uint32_(buffer, len); 2454 2455 FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0); 2456 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8; 2457 if(read_cb(buffer, 1, len, handle) != len) 2458 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2459 block->colors = unpack_uint32_(buffer, len); 2460 2461 /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */ 2462 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) 2463 return status; 2464 2465 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2466} 2467 2468FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2469{ 2470 if(block_length == 0) { 2471 block->data = 0; 2472 } 2473 else { 2474 if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2475 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2476 2477 if(read_cb(block->data, 1, block_length, handle) != block_length) 2478 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2479 } 2480 2481 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2482} 2483 2484FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2485{ 2486 FLAC__ASSERT(0 != file); 2487 FLAC__ASSERT(0 != status); 2488 2489 if(!write_metadata_block_header_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2490 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2491 return false; 2492 } 2493 2494 return true; 2495} 2496 2497FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2498{ 2499 FLAC__ASSERT(0 != file); 2500 FLAC__ASSERT(0 != status); 2501 2502 if (write_metadata_block_data_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2503 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2504 return true; 2505 } 2506 else { 2507 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2508 return false; 2509 } 2510} 2511 2512FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2513{ 2514 FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2515 2516 FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); 2517 2518 buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type; 2519 pack_uint32_(block->length, buffer + 1, 3); 2520 2521 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2522 return false; 2523 2524 return true; 2525} 2526 2527FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2528{ 2529 FLAC__ASSERT(0 != block); 2530 2531 switch(block->type) { 2532 case FLAC__METADATA_TYPE_STREAMINFO: 2533 return write_metadata_block_data_streaminfo_cb_(handle, write_cb, &block->data.stream_info); 2534 case FLAC__METADATA_TYPE_PADDING: 2535 return write_metadata_block_data_padding_cb_(handle, write_cb, &block->data.padding, block->length); 2536 case FLAC__METADATA_TYPE_APPLICATION: 2537 return write_metadata_block_data_application_cb_(handle, write_cb, &block->data.application, block->length); 2538 case FLAC__METADATA_TYPE_SEEKTABLE: 2539 return write_metadata_block_data_seektable_cb_(handle, write_cb, &block->data.seek_table); 2540 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2541 return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment); 2542 case FLAC__METADATA_TYPE_CUESHEET: 2543 return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet); 2544 case FLAC__METADATA_TYPE_PICTURE: 2545 return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture); 2546 default: 2547 return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length); 2548 } 2549} 2550 2551FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block) 2552{ 2553 FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; 2554 const unsigned channels1 = block->channels - 1; 2555 const unsigned bps1 = block->bits_per_sample - 1; 2556 2557 /* we are using hardcoded numbers for simplicity but we should 2558 * probably eventually write a bit-level packer and use the 2559 * _STREAMINFO_ constants. 2560 */ 2561 pack_uint32_(block->min_blocksize, buffer, 2); 2562 pack_uint32_(block->max_blocksize, buffer+2, 2); 2563 pack_uint32_(block->min_framesize, buffer+4, 3); 2564 pack_uint32_(block->max_framesize, buffer+7, 3); 2565 buffer[10] = (block->sample_rate >> 12) & 0xff; 2566 buffer[11] = (block->sample_rate >> 4) & 0xff; 2567 buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4); 2568 buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f)); 2569 pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4); 2570 memcpy(buffer+18, block->md5sum, 16); 2571 2572 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2573 return false; 2574 2575 return true; 2576} 2577 2578FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length) 2579{ 2580 unsigned i, n = block_length; 2581 FLAC__byte buffer[1024]; 2582 2583 (void)block; 2584 2585 memset(buffer, 0, 1024); 2586 2587 for(i = 0; i < n/1024; i++) 2588 if(write_cb(buffer, 1, 1024, handle) != 1024) 2589 return false; 2590 2591 n %= 1024; 2592 2593 if(write_cb(buffer, 1, n, handle) != n) 2594 return false; 2595 2596 return true; 2597} 2598 2599FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length) 2600{ 2601 const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2602 2603 if(write_cb(block->id, 1, id_bytes, handle) != id_bytes) 2604 return false; 2605 2606 block_length -= id_bytes; 2607 2608 if(write_cb(block->data, 1, block_length, handle) != block_length) 2609 return false; 2610 2611 return true; 2612} 2613 2614FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block) 2615{ 2616 unsigned i; 2617 FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2618 2619 for(i = 0; i < block->num_points; i++) { 2620 /* some MAGIC NUMBERs here */ 2621 pack_uint64_(block->points[i].sample_number, buffer, 8); 2622 pack_uint64_(block->points[i].stream_offset, buffer+8, 8); 2623 pack_uint32_(block->points[i].frame_samples, buffer+16, 2); 2624 if(write_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2625 return false; 2626 } 2627 2628 return true; 2629} 2630 2631FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block) 2632{ 2633 unsigned i; 2634 const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2635 const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2636 FLAC__byte buffer[4]; /* magic number is asserted below */ 2637 2638 FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer)); 2639 2640 pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len); 2641 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2642 return false; 2643 if(write_cb(block->vendor_string.entry, 1, block->vendor_string.length, handle) != block->vendor_string.length) 2644 return false; 2645 2646 pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len); 2647 if(write_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2648 return false; 2649 2650 for(i = 0; i < block->num_comments; i++) { 2651 pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len); 2652 if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2653 return false; 2654 if(write_cb(block->comments[i].entry, 1, block->comments[i].length, handle) != block->comments[i].length) 2655 return false; 2656 } 2657 2658 return true; 2659} 2660 2661FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block) 2662{ 2663 unsigned i, j, len; 2664 FLAC__byte buffer[1024]; /* asserted below that this is big enough */ 2665 2666 FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2667 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN/8); 2668 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); 2669 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2670 2671 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2672 len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2673 if(write_cb(block->media_catalog_number, 1, len, handle) != len) 2674 return false; 2675 2676 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2677 len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2678 pack_uint64_(block->lead_in, buffer, len); 2679 if(write_cb(buffer, 1, len, handle) != len) 2680 return false; 2681 2682 FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2683 len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2684 memset(buffer, 0, len); 2685 if(block->is_cd) 2686 buffer[0] |= 0x80; 2687 if(write_cb(buffer, 1, len, handle) != len) 2688 return false; 2689 2690 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2691 len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2692 pack_uint32_(block->num_tracks, buffer, len); 2693 if(write_cb(buffer, 1, len, handle) != len) 2694 return false; 2695 2696 for(i = 0; i < block->num_tracks; i++) { 2697 FLAC__StreamMetadata_CueSheet_Track *track = block->tracks + i; 2698 2699 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2700 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2701 pack_uint64_(track->offset, buffer, len); 2702 if(write_cb(buffer, 1, len, handle) != len) 2703 return false; 2704 2705 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2706 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2707 pack_uint32_(track->number, buffer, len); 2708 if(write_cb(buffer, 1, len, handle) != len) 2709 return false; 2710 2711 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2712 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2713 if(write_cb(track->isrc, 1, len, handle) != len) 2714 return false; 2715 2716 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); 2717 len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2718 memset(buffer, 0, len); 2719 buffer[0] = (track->type << 7) | (track->pre_emphasis << 6); 2720 if(write_cb(buffer, 1, len, handle) != len) 2721 return false; 2722 2723 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2724 len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2725 pack_uint32_(track->num_indices, buffer, len); 2726 if(write_cb(buffer, 1, len, handle) != len) 2727 return false; 2728 2729 for(j = 0; j < track->num_indices; j++) { 2730 FLAC__StreamMetadata_CueSheet_Index *index = track->indices + j; 2731 2732 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2733 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2734 pack_uint64_(index->offset, buffer, len); 2735 if(write_cb(buffer, 1, len, handle) != len) 2736 return false; 2737 2738 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2739 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2740 pack_uint32_(index->number, buffer, len); 2741 if(write_cb(buffer, 1, len, handle) != len) 2742 return false; 2743 2744 FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2745 len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2746 memset(buffer, 0, len); 2747 if(write_cb(buffer, 1, len, handle) != len) 2748 return false; 2749 } 2750 } 2751 2752 return true; 2753} 2754 2755FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block) 2756{ 2757 unsigned len; 2758 size_t slen; 2759 FLAC__byte buffer[4]; /* magic number is asserted below */ 2760 2761 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8); 2762 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8); 2763 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8); 2764 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8); 2765 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8); 2766 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8); 2767 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8); 2768 FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8); 2769 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2770 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8); 2771 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8); 2772 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2773 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2774 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2775 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2776 FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8); 2777 2778 len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8; 2779 pack_uint32_(block->type, buffer, len); 2780 if(write_cb(buffer, 1, len, handle) != len) 2781 return false; 2782 2783 len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8; 2784 slen = strlen(block->mime_type); 2785 pack_uint32_(slen, buffer, len); 2786 if(write_cb(buffer, 1, len, handle) != len) 2787 return false; 2788 if(write_cb(block->mime_type, 1, slen, handle) != slen) 2789 return false; 2790 2791 len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8; 2792 slen = strlen((const char *)block->description); 2793 pack_uint32_(slen, buffer, len); 2794 if(write_cb(buffer, 1, len, handle) != len) 2795 return false; 2796 if(write_cb(block->description, 1, slen, handle) != slen) 2797 return false; 2798 2799 len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8; 2800 pack_uint32_(block->width, buffer, len); 2801 if(write_cb(buffer, 1, len, handle) != len) 2802 return false; 2803 2804 len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8; 2805 pack_uint32_(block->height, buffer, len); 2806 if(write_cb(buffer, 1, len, handle) != len) 2807 return false; 2808 2809 len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8; 2810 pack_uint32_(block->depth, buffer, len); 2811 if(write_cb(buffer, 1, len, handle) != len) 2812 return false; 2813 2814 len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8; 2815 pack_uint32_(block->colors, buffer, len); 2816 if(write_cb(buffer, 1, len, handle) != len) 2817 return false; 2818 2819 len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8; 2820 pack_uint32_(block->data_length, buffer, len); 2821 if(write_cb(buffer, 1, len, handle) != len) 2822 return false; 2823 if(write_cb(block->data, 1, block->data_length, handle) != block->data_length) 2824 return false; 2825 2826 return true; 2827} 2828 2829FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2830{ 2831 if(write_cb(block->data, 1, block_length, handle) != block_length) 2832 return false; 2833 2834 return true; 2835} 2836 2837FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block) 2838{ 2839 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2840 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2841 return false; 2842 } 2843 2844 if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2845 return false; 2846 2847 if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2848 return false; 2849 2850 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2851 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2852 return false; 2853 } 2854 2855 return read_metadata_block_header_(iterator); 2856} 2857 2858FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last) 2859{ 2860 FLAC__StreamMetadata *padding; 2861 2862 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2863 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2864 return false; 2865 } 2866 2867 block->is_last = false; 2868 2869 if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2870 return false; 2871 2872 if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2873 return false; 2874 2875 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) 2876 return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2877 2878 padding->is_last = padding_is_last; 2879 padding->length = padding_length; 2880 2881 if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) { 2882 FLAC__metadata_object_delete(padding); 2883 return false; 2884 } 2885 2886 if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) { 2887 FLAC__metadata_object_delete(padding); 2888 return false; 2889 } 2890 2891 FLAC__metadata_object_delete(padding); 2892 2893 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2894 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2895 return false; 2896 } 2897 2898 return read_metadata_block_header_(iterator); 2899} 2900 2901FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append) 2902{ 2903 FILE *tempfile; 2904 char *tempfilename; 2905 int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */ 2906 off_t fixup_is_last_flag_offset = -1; 2907 2908 FLAC__ASSERT(0 != block || append == false); 2909 2910 if(iterator->is_last) { 2911 if(append) { 2912 fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */ 2913 fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2914 } 2915 else if(0 == block) { 2916 simple_iterator_push_(iterator); 2917 if(!FLAC__metadata_simple_iterator_prev(iterator)) { 2918 (void)simple_iterator_pop_(iterator); 2919 return false; 2920 } 2921 fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */ 2922 fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2923 if(!simple_iterator_pop_(iterator)) 2924 return false; 2925 } 2926 } 2927 2928 if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append)) 2929 return false; 2930 2931 if(0 != block) { 2932 if(!write_metadata_block_header_(tempfile, &iterator->status, block)) { 2933 cleanup_tempfile_(&tempfile, &tempfilename); 2934 return false; 2935 } 2936 2937 if(!write_metadata_block_data_(tempfile, &iterator->status, block)) { 2938 cleanup_tempfile_(&tempfile, &tempfilename); 2939 return false; 2940 } 2941 } 2942 2943 if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0)) 2944 return false; 2945 2946 if(append) 2947 return FLAC__metadata_simple_iterator_next(iterator); 2948 2949 return true; 2950} 2951 2952void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator) 2953{ 2954 FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH); 2955 iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth]; 2956 iterator->depth++; 2957} 2958 2959FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator) 2960{ 2961 FLAC__ASSERT(iterator->depth > 0); 2962 iterator->depth--; 2963 if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2964 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2965 return false; 2966 } 2967 2968 return read_metadata_block_header_(iterator); 2969} 2970 2971/* return meanings: 2972 * 0: ok 2973 * 1: read error 2974 * 2: seek error 2975 * 3: not a FLAC file 2976 */ 2977unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb) 2978{ 2979 FLAC__byte buffer[4]; 2980 size_t n; 2981 unsigned i; 2982 2983 FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer)); 2984 2985 /* skip any id3v2 tag */ 2986 errno = 0; 2987 n = read_cb(buffer, 1, 4, handle); 2988 if(errno) 2989 return 1; 2990 else if(n != 4) 2991 return 3; 2992 else if(0 == memcmp(buffer, "ID3", 3)) { 2993 unsigned tag_length = 0; 2994 2995 /* skip to the tag length */ 2996 if(seek_cb(handle, 2, SEEK_CUR) < 0) 2997 return 2; 2998 2999 /* read the length */ 3000 for(i = 0; i < 4; i++) { 3001 if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80) 3002 return 1; 3003 tag_length <<= 7; 3004 tag_length |= (buffer[0] & 0x7f); 3005 } 3006 3007 /* skip the rest of the tag */ 3008 if(seek_cb(handle, tag_length, SEEK_CUR) < 0) 3009 return 2; 3010 3011 /* read the stream sync code */ 3012 errno = 0; 3013 n = read_cb(buffer, 1, 4, handle); 3014 if(errno) 3015 return 1; 3016 else if(n != 4) 3017 return 3; 3018 } 3019 3020 /* check for the fLaC signature */ 3021 if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH)) 3022 return 0; 3023 else 3024 return 3; 3025} 3026 3027unsigned seek_to_first_metadata_block_(FILE *f) 3028{ 3029 return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_); 3030} 3031 3032FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append) 3033{ 3034 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]; 3035 3036 if(0 != fseeko(iterator->file, 0, SEEK_SET)) { 3037 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3038 return false; 3039 } 3040 if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) { 3041 cleanup_tempfile_(tempfile, tempfilename); 3042 return false; 3043 } 3044 if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) { 3045 cleanup_tempfile_(tempfile, tempfilename); 3046 return false; 3047 } 3048 3049 return true; 3050} 3051 3052FLAC__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) 3053{ 3054 off_t save_offset = iterator->offset[iterator->depth]; 3055 FLAC__ASSERT(0 != *tempfile); 3056 3057 if(0 != fseeko(iterator->file, save_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length, SEEK_SET)) { 3058 cleanup_tempfile_(tempfile, tempfilename); 3059 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3060 return false; 3061 } 3062 if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) { 3063 cleanup_tempfile_(tempfile, tempfilename); 3064 return false; 3065 } 3066 3067 if(fixup_is_last_code != 0) { 3068 /* 3069 * if code == 1, it means a block was appended to the end so 3070 * we have to clear the is_last flag of the previous block 3071 * if code == -1, it means the last block was deleted so 3072 * we have to set the is_last flag of the previous block 3073 */ 3074 /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */ 3075 FLAC__byte x; 3076 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3077 cleanup_tempfile_(tempfile, tempfilename); 3078 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3079 return false; 3080 } 3081 if(fread(&x, 1, 1, *tempfile) != 1) { 3082 cleanup_tempfile_(tempfile, tempfilename); 3083 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3084 return false; 3085 } 3086 if(fixup_is_last_code > 0) { 3087 FLAC__ASSERT(x & 0x80); 3088 x &= 0x7f; 3089 } 3090 else { 3091 FLAC__ASSERT(!(x & 0x80)); 3092 x |= 0x80; 3093 } 3094 if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3095 cleanup_tempfile_(tempfile, tempfilename); 3096 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3097 return false; 3098 } 3099 if(local__fwrite(&x, 1, 1, *tempfile) != 1) { 3100 cleanup_tempfile_(tempfile, tempfilename); 3101 iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3102 return false; 3103 } 3104 } 3105 3106 (void)fclose(iterator->file); 3107 3108 if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status)) 3109 return false; 3110 3111 if(iterator->has_stats) 3112 set_file_stats_(iterator->filename, &iterator->stats); 3113 3114 if(!simple_iterator_prime_input_(iterator, !iterator->is_writable)) 3115 return false; 3116 if(backup) { 3117 while(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length < save_offset) 3118 if(!FLAC__metadata_simple_iterator_next(iterator)) 3119 return false; 3120 return true; 3121 } 3122 else { 3123 /* move the iterator to it's original block faster by faking a push, then doing a pop_ */ 3124 FLAC__ASSERT(iterator->depth == 0); 3125 iterator->offset[0] = save_offset; 3126 iterator->depth++; 3127 return simple_iterator_pop_(iterator); 3128 } 3129} 3130 3131FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) 3132{ 3133 FLAC__byte buffer[8192]; 3134 size_t n; 3135 3136 FLAC__ASSERT(bytes >= 0); 3137 while(bytes > 0) { 3138 n = min(sizeof(buffer), (size_t)bytes); 3139 if(fread(buffer, 1, n, file) != n) { 3140 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3141 return false; 3142 } 3143 if(local__fwrite(buffer, 1, n, tempfile) != n) { 3144 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3145 return false; 3146 } 3147 bytes -= n; 3148 } 3149 3150 return true; 3151} 3152 3153FLAC__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) 3154{ 3155 FLAC__byte buffer[8192]; 3156 size_t n; 3157 3158 FLAC__ASSERT(bytes >= 0); 3159 while(bytes > 0) { 3160 n = min(sizeof(buffer), (size_t)bytes); 3161 if(read_cb(buffer, 1, n, handle) != n) { 3162 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3163 return false; 3164 } 3165 if(temp_write_cb(buffer, 1, n, temp_handle) != n) { 3166 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3167 return false; 3168 } 3169 bytes -= n; 3170 } 3171 3172 return true; 3173} 3174 3175FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status) 3176{ 3177 FLAC__byte buffer[8192]; 3178 size_t n; 3179 3180 while(!feof(file)) { 3181 n = fread(buffer, 1, sizeof(buffer), file); 3182 if(n == 0 && !feof(file)) { 3183 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3184 return false; 3185 } 3186 if(n > 0 && local__fwrite(buffer, 1, n, tempfile) != n) { 3187 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3188 return false; 3189 } 3190 } 3191 3192 return true; 3193} 3194 3195FLAC__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) 3196{ 3197 FLAC__byte buffer[8192]; 3198 size_t n; 3199 3200 while(!eof_cb(handle)) { 3201 n = read_cb(buffer, 1, sizeof(buffer), handle); 3202 if(n == 0 && !eof_cb(handle)) { 3203 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3204 return false; 3205 } 3206 if(n > 0 && temp_write_cb(buffer, 1, n, temp_handle) != n) { 3207 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3208 return false; 3209 } 3210 } 3211 3212 return true; 3213} 3214 3215FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3216{ 3217 static const char *tempfile_suffix = ".metadata_edit"; 3218 if(0 == tempfile_path_prefix) { 3219 if(0 == (*tempfilename = (char*)safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) { 3220 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3221 return false; 3222 } 3223 strcpy(*tempfilename, filename); 3224 strcat(*tempfilename, tempfile_suffix); 3225 } 3226 else { 3227 const char *p = strrchr(filename, '/'); 3228 if(0 == p) 3229 p = filename; 3230 else 3231 p++; 3232 3233 if(0 == (*tempfilename = (char*)safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) { 3234 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3235 return false; 3236 } 3237 strcpy(*tempfilename, tempfile_path_prefix); 3238 strcat(*tempfilename, "/"); 3239 strcat(*tempfilename, p); 3240 strcat(*tempfilename, tempfile_suffix); 3241 } 3242 3243 if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) { 3244 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 3245 return false; 3246 } 3247 3248 return true; 3249} 3250 3251FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3252{ 3253 FLAC__ASSERT(0 != filename); 3254 FLAC__ASSERT(0 != tempfile); 3255 FLAC__ASSERT(0 != *tempfile); 3256 FLAC__ASSERT(0 != tempfilename); 3257 FLAC__ASSERT(0 != *tempfilename); 3258 FLAC__ASSERT(0 != status); 3259 3260 (void)fclose(*tempfile); 3261 *tempfile = 0; 3262 3263#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__ 3264 /* on some flavors of windows, rename() will fail if the destination already exists */ 3265 if(unlink(filename) < 0) { 3266 cleanup_tempfile_(tempfile, tempfilename); 3267 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR; 3268 return false; 3269 } 3270#endif 3271 3272 /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */ 3273 if(0 != rename(*tempfilename, filename)) { 3274 cleanup_tempfile_(tempfile, tempfilename); 3275 *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR; 3276 return false; 3277 } 3278 3279 cleanup_tempfile_(tempfile, tempfilename); 3280 3281 return true; 3282} 3283 3284void cleanup_tempfile_(FILE **tempfile, char **tempfilename) 3285{ 3286 if(0 != *tempfile) { 3287 (void)fclose(*tempfile); 3288 *tempfile = 0; 3289 } 3290 3291 if(0 != *tempfilename) { 3292 (void)unlink(*tempfilename); 3293 free(*tempfilename); 3294 *tempfilename = 0; 3295 } 3296} 3297 3298FLAC__bool get_file_stats_(const char *filename, struct stat *stats) 3299{ 3300 FLAC__ASSERT(0 != filename); 3301 FLAC__ASSERT(0 != stats); 3302 return (0 == stat(filename, stats)); 3303} 3304 3305void set_file_stats_(const char *filename, struct stat *stats) 3306{ 3307 struct utimbuf srctime; 3308 3309 FLAC__ASSERT(0 != filename); 3310 FLAC__ASSERT(0 != stats); 3311 3312 srctime.actime = stats->st_atime; 3313 srctime.modtime = stats->st_mtime; 3314 (void)chmod(filename, stats->st_mode); 3315 (void)utime(filename, &srctime); 3316#if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__ && !defined __EMX__ 3317 (void)chown(filename, stats->st_uid, -1); 3318 (void)chown(filename, -1, stats->st_gid); 3319#endif 3320} 3321 3322int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence) 3323{ 3324 return fseeko((FILE*)handle, (off_t)offset, whence); 3325} 3326 3327FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle) 3328{ 3329 return ftello((FILE*)handle); 3330} 3331 3332FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status) 3333{ 3334 switch(status) { 3335 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK: 3336 return FLAC__METADATA_CHAIN_STATUS_OK; 3337 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: 3338 return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT; 3339 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: 3340 return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 3341 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: 3342 return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; 3343 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE: 3344 return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE; 3345 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA: 3346 return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA; 3347 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR: 3348 return FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 3349 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR: 3350 return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 3351 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR: 3352 return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 3353 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR: 3354 return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR; 3355 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR: 3356 return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR; 3357 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR: 3358 return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 3359 case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR: 3360 default: 3361 return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 3362 } 3363} 3364