109
124
static unsigned seek_to_first_metadata_block_(FILE *f);
111
126
static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append);
112
static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, long fixup_is_last_flag_offset, FLAC__bool backup);
127
static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup);
114
static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status);
115
static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status);
129
static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
130
static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
116
131
static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status);
117
132
static FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status);
148
163
***************************************************************************/
150
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
151
static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
152
static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
165
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
166
static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
167
static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
155
170
FLAC__bool got_error;
156
FLAC__bool got_object;
157
171
FLAC__StreamMetadata *object;
158
172
} level0_client_data;
174
static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
176
level0_client_data cd;
177
FLAC__StreamDecoder *decoder;
179
FLAC__ASSERT(0 != filename);
181
cd.got_error = false;
184
decoder = FLAC__stream_decoder_new();
189
FLAC__stream_decoder_set_md5_checking(decoder, false);
190
FLAC__stream_decoder_set_metadata_ignore_all(decoder);
191
FLAC__stream_decoder_set_metadata_respond(decoder, type);
193
if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) {
194
(void)FLAC__stream_decoder_finish(decoder);
195
FLAC__stream_decoder_delete(decoder);
199
if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
200
(void)FLAC__stream_decoder_finish(decoder);
201
FLAC__stream_decoder_delete(decoder);
203
FLAC__metadata_object_delete(cd.object);
207
(void)FLAC__stream_decoder_finish(decoder);
208
FLAC__stream_decoder_delete(decoder);
160
213
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
162
level0_client_data cd;
163
FLAC__FileDecoder *decoder;
215
FLAC__StreamMetadata *object;
165
217
FLAC__ASSERT(0 != filename);
166
218
FLAC__ASSERT(0 != streaminfo);
168
decoder = FLAC__file_decoder_new();
173
cd.got_error = false;
174
cd.got_object = false;
177
FLAC__file_decoder_set_md5_checking(decoder, false);
178
FLAC__file_decoder_set_filename(decoder, filename);
179
FLAC__file_decoder_set_metadata_ignore_all(decoder);
180
FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
181
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
182
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
183
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
184
FLAC__file_decoder_set_client_data(decoder, &cd);
186
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
187
FLAC__file_decoder_finish(decoder);
188
FLAC__file_decoder_delete(decoder);
192
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
193
FLAC__file_decoder_finish(decoder);
194
FLAC__file_decoder_delete(decoder);
196
FLAC__metadata_object_delete(cd.object);
200
FLAC__file_decoder_finish(decoder);
201
FLAC__file_decoder_delete(decoder);
220
object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO);
204
223
/* can just copy the contents since STREAMINFO has no internal structure */
205
*streaminfo = *(cd.object);
209
FLAC__metadata_object_delete(cd.object);
211
return cd.got_object;
224
*streaminfo = *object;
225
FLAC__metadata_object_delete(object);
214
233
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
216
level0_client_data cd;
217
FLAC__FileDecoder *decoder;
219
235
FLAC__ASSERT(0 != filename);
220
236
FLAC__ASSERT(0 != tags);
222
decoder = FLAC__file_decoder_new();
229
cd.got_error = false;
230
cd.got_object = false;
233
FLAC__file_decoder_set_md5_checking(decoder, false);
234
FLAC__file_decoder_set_filename(decoder, filename);
235
FLAC__file_decoder_set_metadata_ignore_all(decoder);
236
FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
237
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
238
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
239
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
240
FLAC__file_decoder_set_client_data(decoder, &cd);
242
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
243
FLAC__file_decoder_finish(decoder);
244
FLAC__file_decoder_delete(decoder);
248
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
249
FLAC__file_decoder_finish(decoder);
250
FLAC__file_decoder_delete(decoder);
252
FLAC__metadata_object_delete(cd.object);
256
FLAC__file_decoder_finish(decoder);
257
FLAC__file_decoder_delete(decoder);
262
return cd.got_object;
265
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
238
*tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT);
243
FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet)
245
FLAC__ASSERT(0 != filename);
246
FLAC__ASSERT(0 != cuesheet);
248
*cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET);
250
return 0 != *cuesheet;
253
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
267
255
(void)decoder, (void)frame, (void)buffer, (void)client_data;
269
257
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
272
void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
260
void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
274
262
level0_client_data *cd = (level0_client_data *)client_data;
295
281
cd->got_error = true;
284
FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors)
286
FLAC__Metadata_SimpleIterator *it;
287
FLAC__uint64 max_area_seen = 0;
288
FLAC__uint64 max_depth_seen = 0;
290
FLAC__ASSERT(0 != filename);
291
FLAC__ASSERT(0 != picture);
295
it = FLAC__metadata_simple_iterator_new();
298
if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
299
FLAC__metadata_simple_iterator_delete(it);
303
if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
304
FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
305
FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
306
/* check constraints */
308
(type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
309
(mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
310
(description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
311
obj->data.picture.width <= max_width &&
312
obj->data.picture.height <= max_height &&
313
obj->data.picture.depth <= max_depth &&
314
obj->data.picture.colors <= max_colors &&
315
(area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
318
FLAC__metadata_object_delete(*picture);
320
max_area_seen = area;
321
max_depth_seen = obj->data.picture.depth;
324
FLAC__metadata_object_delete(obj);
327
} while(FLAC__metadata_simple_iterator_next(it));
329
FLAC__metadata_simple_iterator_delete(it);
331
return (0 != *picture);
299
335
/****************************************************************************
737
772
if(padding_leftover == 0) {
738
773
ret = write_metadata_block_stationary_(iterator, block);
739
774
FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
740
FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
775
FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
744
779
FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
745
780
ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
746
781
FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
747
FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
782
FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
752
787
ret = rewrite_whole_file_(iterator, block, /*append=*/true);
753
788
FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset);
754
FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
789
FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
759
794
FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding)
761
FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
796
FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];)
764
799
if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
1019
1060
/* WATCHOUT: Make sure to also update the logic in
1020
1061
* FLAC__metadata_chain_check_if_tempfile_needed() if the logic here changes.
1022
static unsigned chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
1063
static off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
1024
unsigned current_length = chain_calculate_length_(chain);
1065
off_t current_length = chain_calculate_length_(chain);
1026
1067
if(use_padding) {
1027
1068
/* if the metadata shrank and the last block is padding, we just extend the last padding block */
1028
1069
if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1029
const unsigned delta = chain->initial_length - current_length;
1070
const off_t delta = chain->initial_length - current_length;
1030
1071
chain->tail->data->length += delta;
1031
1072
current_length += delta;
1032
1073
FLAC__ASSERT(current_length == chain->initial_length);
1034
1075
/* if the metadata shrank more than 4 bytes then there's room to add another padding block */
1035
else if(current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
1076
else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) {
1036
1077
FLAC__StreamMetadata *padding;
1037
1078
FLAC__Metadata_Node *node;
1038
1079
if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) {
1149
1190
chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1152
chain->last_offset = (long)pos;
1193
chain->last_offset = (off_t)pos;
1196
chain->initial_length = chain_calculate_length_(chain);
1201
FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
1203
FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1205
if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) {
1206
*bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle);
1208
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
1210
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
1213
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
1216
static FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
1218
(void)decoder, (void)frame, (void)buffer, (void)client_data;
1219
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
1222
static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
1224
FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1225
FLAC__Metadata_Node *node;
1231
chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1235
node->data = FLAC__metadata_object_clone(metadata);
1236
if(0 == node->data) {
1238
chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1242
chain_append_node_(chain, node);
1245
static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
1247
FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
1248
(void)decoder, (void)status;
1249
chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1252
static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb)
1254
FLAC__StreamDecoder *decoder;
1256
FLAC__ASSERT(0 != chain);
1258
/* we assume we're already at the beginning of the file */
1260
chain->handle = handle;
1261
chain->read_cb = read_cb;
1262
if(0 == (decoder = FLAC__stream_decoder_new())) {
1263
chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
1266
FLAC__stream_decoder_set_metadata_respond_all(decoder);
1267
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) {
1268
FLAC__stream_decoder_delete(decoder);
1269
chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1273
chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
1275
if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
1276
chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */
1277
if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) {
1278
FLAC__stream_decoder_delete(decoder);
1282
FLAC__stream_decoder_delete(decoder);
1284
chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
1155
1286
chain->initial_length = chain_calculate_length_(chain);
1487
chain->is_ogg = is_ogg;
1356
1489
if(0 == (file = fopen(filename, "rb"))) {
1357
1490
chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1361
/* chain_read_cb_() sets chain->status for us */
1362
ret = chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_);
1494
/* the function also sets chain->status for us */
1496
chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) :
1497
chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_)
1505
FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
1507
return chain_read_(chain, filename, /*is_ogg=*/false);
1510
FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename)
1512
return chain_read_(chain, filename, /*is_ogg=*/true);
1515
static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg)
1519
FLAC__ASSERT(0 != chain);
1521
chain_clear_(chain);
1523
if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
1524
chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1528
chain->is_ogg = is_ogg;
1531
if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
1532
chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1536
/* the function also sets chain->status for us */
1538
chain_read_ogg_cb_(chain, handle, callbacks.read) :
1539
chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell)
1369
1545
FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1371
FLAC__ASSERT(0 != chain);
1373
chain_clear_(chain);
1375
if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
1376
chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1381
if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
1382
chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1386
if(!chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell))
1387
return false; /* chain->status is already set by chain_read_cb_ */
1547
return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false);
1550
FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1552
return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true);
1392
1555
FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
2139
2318
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2321
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)
2323
FLAC__byte buffer[sizeof(FLAC__uint32)];
2325
FLAC__ASSERT(0 != data);
2326
FLAC__ASSERT(length_len%8 == 0);
2328
length_len /= 8; /* convert to bytes */
2330
FLAC__ASSERT(sizeof(buffer) >= length_len);
2332
if(read_cb(buffer, 1, length_len, handle) != length_len)
2333
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2334
*length = unpack_uint32_(buffer, length_len);
2339
if(0 == (*data = (FLAC__byte*)malloc(*length+1)))
2340
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
2343
if(read_cb(*data, 1, *length, handle) != *length)
2344
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2347
(*data)[*length] = '\0';
2349
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2352
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block)
2354
FLAC__Metadata_SimpleIteratorStatus status;
2355
FLAC__byte buffer[4]; /* asserted below that this is big enough */
2358
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
2359
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
2360
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
2361
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
2362
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8);
2364
FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0);
2365
len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8;
2366
if(read_cb(buffer, 1, len, handle) != len)
2367
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2368
block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len);
2370
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)
2373
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)
2376
FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0);
2377
len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8;
2378
if(read_cb(buffer, 1, len, handle) != len)
2379
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2380
block->width = unpack_uint32_(buffer, len);
2382
FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0);
2383
len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8;
2384
if(read_cb(buffer, 1, len, handle) != len)
2385
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2386
block->height = unpack_uint32_(buffer, len);
2388
FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0);
2389
len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8;
2390
if(read_cb(buffer, 1, len, handle) != len)
2391
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2392
block->depth = unpack_uint32_(buffer, len);
2394
FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0);
2395
len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8;
2396
if(read_cb(buffer, 1, len, handle) != len)
2397
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2398
block->colors = unpack_uint32_(buffer, len);
2400
/* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */
2401
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)
2404
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2142
2407
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length)
2144
2409
if(block_length == 0) {
2694
FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block)
2698
FLAC__byte buffer[4]; /* magic number is asserted below */
2700
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8);
2701
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8);
2702
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8);
2703
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8);
2704
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8);
2705
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8);
2706
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8);
2707
FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8);
2708
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
2709
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8);
2710
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8);
2711
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
2712
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
2713
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
2714
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8);
2715
FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8);
2717
len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8;
2718
pack_uint32_(block->type, buffer, len);
2719
if(write_cb(buffer, 1, len, handle) != len)
2722
len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8;
2723
slen = strlen(block->mime_type);
2724
pack_uint32_(slen, buffer, len);
2725
if(write_cb(buffer, 1, len, handle) != len)
2727
if(write_cb(block->mime_type, 1, slen, handle) != slen)
2730
len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8;
2731
slen = strlen((const char *)block->description);
2732
pack_uint32_(slen, buffer, len);
2733
if(write_cb(buffer, 1, len, handle) != len)
2735
if(write_cb(block->description, 1, slen, handle) != slen)
2738
len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8;
2739
pack_uint32_(block->width, buffer, len);
2740
if(write_cb(buffer, 1, len, handle) != len)
2743
len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8;
2744
pack_uint32_(block->height, buffer, len);
2745
if(write_cb(buffer, 1, len, handle) != len)
2748
len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8;
2749
pack_uint32_(block->depth, buffer, len);
2750
if(write_cb(buffer, 1, len, handle) != len)
2753
len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8;
2754
pack_uint32_(block->colors, buffer, len);
2755
if(write_cb(buffer, 1, len, handle) != len)
2758
len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8;
2759
pack_uint32_(block->data_length, buffer, len);
2760
if(write_cb(buffer, 1, len, handle) != len)
2762
if(write_cb(block->data, 1, block->data_length, handle) != block->data_length)
2427
2768
FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length)
2429
2770
if(write_cb(block->data, 1, block_length, handle) != block_length)
2908
3252
srctime.modtime = stats->st_mtime;
2909
3253
(void)chmod(filename, stats->st_mode);
2910
3254
(void)utime(filename, &srctime);
2911
#if !defined _MSC_VER && !defined __MINGW32__
3255
#if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__ && !defined __EMX__
2912
3256
(void)chown(filename, stats->st_uid, -1);
2913
3257
(void)chown(filename, -1, stats->st_gid);
2918
* We cast FLAC__int64 to long and use fseek()/ftell() because
2919
* none of our operations on metadata is ever likely to go past
2922
3261
int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
2924
FLAC__ASSERT(offset <= 0x7fffffff);
2925
return fseek((FILE*)handle, (long)offset, whence);
3263
return fseeko((FILE*)handle, (off_t)offset, whence);
2928
3266
FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle)
2930
return (long)ftell((FILE*)handle);
3268
return ftello((FILE*)handle);
2933
3271
FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)