~ubuntu-branches/ubuntu/precise/flac/precise-updates

« back to all changes in this revision

Viewing changes to src/libFLAC/metadata_iterators.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-05-29 22:56:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070529225636-ljeff8xxip09qaap
Tags: 1.1.4-1
* New upstream release. closes: #405167, #411311
  - libOggFLAC and libOggFLAC++ have been merged into libFLAC, so
    remove their corresponding packages.
  - Because of the API changes required to effect the above, there has
    been yet another soname bump. libflac7 -> libflac8 and
    libflac++5 -> libflac++6. Emails have been dispatched to the
    maintainers of dependent packages.
* Some notes on patches that were removed:
  - 02_stdin_stdout, 06_manpage_mention_utf8_convert: merged upstream
  - 08_manpage_warnings: Upstream has changed the manpage so it defintely
    can't fit in in 80 cols, so just forget about it. We'll live.
  - 05_eof_warnings_are_errors: Upstream decided to add a -w option to
    flac to treat all warnings as errors. I am going to defer to that
    for now, but if people think it's stupid let me know and I'll port
    the patch forward.
  - 04_stack_smasher: was a backport from 1.1.3, so it's obsolete.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* libFLAC - Free Lossless Audio Codec library
2
 
 * Copyright (C) 2001,2002,2003,2004,2005  Josh Coalson
 
2
 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007  Josh Coalson
3
3
 *
4
4
 * Redistribution and use in source and binary forms, with or without
5
5
 * modification, are permitted provided that the following conditions
29
29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 */
31
31
 
 
32
#if HAVE_CONFIG_H
 
33
#  include <config.h>
 
34
#endif
 
35
 
32
36
#include <errno.h>
33
37
#include <stdio.h>
34
38
#include <stdlib.h>
35
39
#include <string.h>
36
40
 
37
 
#if defined _MSC_VER || defined __MINGW32__
 
41
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
 
42
#if defined __BORLANDC__
 
43
#include <utime.h> /* for utime() */
 
44
#else
38
45
#include <sys/utime.h> /* for utime() */
 
46
#endif
39
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
40
53
#else
41
54
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
42
55
#include <utime.h> /* for utime() */
47
60
#include "private/metadata.h"
48
61
 
49
62
#include "FLAC/assert.h"
50
 
#include "FLAC/file_decoder.h"
 
63
#include "FLAC/stream_decoder.h"
51
64
 
52
65
#ifdef max
53
66
#undef max
84
97
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block);
85
98
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track);
86
99
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block);
 
100
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block);
87
101
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length);
88
102
 
89
103
static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
96
110
static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block);
97
111
static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block);
98
112
static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block);
 
113
static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block);
99
114
static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length);
100
115
 
101
116
static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
109
124
static unsigned seek_to_first_metadata_block_(FILE *f);
110
125
 
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);
113
128
 
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);
118
133
 
147
162
 *
148
163
 ***************************************************************************/
149
164
 
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);
153
168
 
154
169
typedef struct {
155
170
        FLAC__bool got_error;
156
 
        FLAC__bool got_object;
157
171
        FLAC__StreamMetadata *object;
158
172
} level0_client_data;
159
173
 
 
174
static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
 
175
{
 
176
        level0_client_data cd;
 
177
        FLAC__StreamDecoder *decoder;
 
178
 
 
179
        FLAC__ASSERT(0 != filename);
 
180
 
 
181
        cd.got_error = false;
 
182
        cd.object = 0;
 
183
 
 
184
        decoder = FLAC__stream_decoder_new();
 
185
 
 
186
        if(0 == decoder)
 
187
                return 0;
 
188
 
 
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);
 
192
 
 
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);
 
196
                return 0;
 
197
        }
 
198
 
 
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);
 
202
                if(0 != cd.object)
 
203
                        FLAC__metadata_object_delete(cd.object);
 
204
                return 0;
 
205
        }
 
206
 
 
207
        (void)FLAC__stream_decoder_finish(decoder);
 
208
        FLAC__stream_decoder_delete(decoder);
 
209
 
 
210
        return cd.object;
 
211
}
 
212
 
160
213
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
161
214
{
162
 
        level0_client_data cd;
163
 
        FLAC__FileDecoder *decoder;
 
215
        FLAC__StreamMetadata *object;
164
216
 
165
217
        FLAC__ASSERT(0 != filename);
166
218
        FLAC__ASSERT(0 != streaminfo);
167
219
 
168
 
        decoder = FLAC__file_decoder_new();
169
 
 
170
 
        if(0 == decoder)
171
 
                return false;
172
 
 
173
 
        cd.got_error = false;
174
 
        cd.got_object = false;
175
 
        cd.object = 0;
176
 
 
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);
185
 
 
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);
189
 
                return false;
190
 
        }
191
 
 
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);
195
 
                if(0 != cd.object)
196
 
                        FLAC__metadata_object_delete(cd.object);
197
 
                return false;
198
 
        }
199
 
 
200
 
        FLAC__file_decoder_finish(decoder);
201
 
        FLAC__file_decoder_delete(decoder);
202
 
 
203
 
        if(cd.got_object) {
 
220
        object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO);
 
221
 
 
222
        if (object) {
204
223
                /* can just copy the contents since STREAMINFO has no internal structure */
205
 
                *streaminfo = *(cd.object);
206
 
        }
207
 
 
208
 
        if(0 != cd.object)
209
 
                FLAC__metadata_object_delete(cd.object);
210
 
 
211
 
        return cd.got_object;
 
224
                *streaminfo = *object;
 
225
                FLAC__metadata_object_delete(object);
 
226
                return true;
 
227
        }
 
228
        else {
 
229
                return false;
 
230
        }
212
231
}
213
232
 
214
233
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
215
234
{
216
 
        level0_client_data cd;
217
 
        FLAC__FileDecoder *decoder;
218
 
 
219
235
        FLAC__ASSERT(0 != filename);
220
236
        FLAC__ASSERT(0 != tags);
221
237
 
222
 
        decoder = FLAC__file_decoder_new();
223
 
 
224
 
        if(0 == decoder)
225
 
                return false;
226
 
 
227
 
        *tags = 0;
228
 
 
229
 
        cd.got_error = false;
230
 
        cd.got_object = false;
231
 
        cd.object = 0;
232
 
 
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);
241
 
 
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);
245
 
                return false;
246
 
        }
247
 
 
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);
251
 
                if(0 != cd.object)
252
 
                        FLAC__metadata_object_delete(cd.object);
253
 
                return false;
254
 
        }
255
 
 
256
 
        FLAC__file_decoder_finish(decoder);
257
 
        FLAC__file_decoder_delete(decoder);
258
 
 
259
 
        if(cd.got_object)
260
 
                *tags = cd.object;
261
 
 
262
 
        return cd.got_object;
263
 
}
264
 
 
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);
 
239
 
 
240
        return 0 != *tags;
 
241
}
 
242
 
 
243
FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet)
 
244
{
 
245
        FLAC__ASSERT(0 != filename);
 
246
        FLAC__ASSERT(0 != cuesheet);
 
247
 
 
248
        *cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET);
 
249
 
 
250
        return 0 != *cuesheet;
 
251
}
 
252
 
 
253
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
266
254
{
267
255
        (void)decoder, (void)frame, (void)buffer, (void)client_data;
268
256
 
269
257
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
270
258
}
271
259
 
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)
273
261
{
274
262
        level0_client_data *cd = (level0_client_data *)client_data;
275
263
        (void)decoder;
278
266
         * we assume we only get here when the one metadata block we were
279
267
         * looking for was passed to us
280
268
         */
281
 
        if(!cd->got_object) {
 
269
        if(!cd->got_error && 0 == cd->object) {
282
270
                if(0 == (cd->object = FLAC__metadata_object_clone(metadata)))
283
271
                        cd->got_error = true;
284
 
                else
285
 
                        cd->got_object = true;
286
272
        }
287
273
}
288
274
 
289
 
void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 
275
void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
290
276
{
291
277
        level0_client_data *cd = (level0_client_data *)client_data;
292
278
        (void)decoder;
295
281
                cd->got_error = true;
296
282
}
297
283
 
 
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)
 
285
{
 
286
        FLAC__Metadata_SimpleIterator *it;
 
287
        FLAC__uint64 max_area_seen = 0;
 
288
        FLAC__uint64 max_depth_seen = 0;
 
289
 
 
290
        FLAC__ASSERT(0 != filename);
 
291
        FLAC__ASSERT(0 != picture);
 
292
 
 
293
        *picture = 0;
 
294
 
 
295
        it = FLAC__metadata_simple_iterator_new();
 
296
        if(0 == it)
 
297
                return false;
 
298
        if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
 
299
                FLAC__metadata_simple_iterator_delete(it);
 
300
                return false;
 
301
        }
 
302
        do {
 
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 */
 
307
                        if(
 
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))
 
316
                        ) {
 
317
                                if(*picture)
 
318
                                        FLAC__metadata_object_delete(*picture);
 
319
                                *picture = obj;
 
320
                                max_area_seen = area;
 
321
                                max_depth_seen = obj->data.picture.depth;
 
322
                        }
 
323
                        else {
 
324
                                FLAC__metadata_object_delete(obj);
 
325
                        }
 
326
                }
 
327
        } while(FLAC__metadata_simple_iterator_next(it));
 
328
 
 
329
        FLAC__metadata_simple_iterator_delete(it);
 
330
 
 
331
        return (0 != *picture);
 
332
}
 
333
 
298
334
 
299
335
/****************************************************************************
300
336
 *
312
348
        FLAC__bool has_stats;
313
349
        FLAC__bool is_writable;
314
350
        FLAC__Metadata_SimpleIteratorStatus status;
315
 
        /*@@@ 2G limits here because of the offset type: */
316
 
        long offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
317
 
        long first_offset; /* this is the offset to the STREAMINFO block */
 
351
        off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
 
352
        off_t first_offset; /* this is the offset to the STREAMINFO block */
318
353
        unsigned depth;
319
354
        /* this is the metadata block header of the current block we are pointing to: */
320
355
        FLAC__bool is_last;
339
374
};
340
375
 
341
376
 
342
 
FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new()
 
377
FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void)
343
378
{
344
379
        FLAC__Metadata_SimpleIterator *iterator = (FLAC__Metadata_SimpleIterator*)calloc(1, sizeof(FLAC__Metadata_SimpleIterator));
345
380
 
423
458
        switch(ret) {
424
459
                case 0:
425
460
                        iterator->depth = 0;
426
 
                        iterator->first_offset = iterator->offset[iterator->depth] = ftell(iterator->file);
 
461
                        iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file);
427
462
                        return read_metadata_block_header_(iterator);
428
463
                case 1:
429
464
                        iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
498
533
        if(iterator->is_last)
499
534
                return false;
500
535
 
501
 
        if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
 
536
        if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) {
502
537
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
503
538
                return false;
504
539
        }
505
540
 
506
 
        iterator->offset[iterator->depth] = ftell(iterator->file);
 
541
        iterator->offset[iterator->depth] = ftello(iterator->file);
507
542
 
508
543
        return read_metadata_block_header_(iterator);
509
544
}
510
545
 
511
546
FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator)
512
547
{
513
 
        long this_offset;
 
548
        off_t this_offset;
514
549
 
515
550
        FLAC__ASSERT(0 != iterator);
516
551
        FLAC__ASSERT(0 != iterator->file);
518
553
        if(iterator->offset[iterator->depth] == iterator->first_offset)
519
554
                return false;
520
555
 
521
 
        if(0 != fseek(iterator->file, iterator->first_offset, SEEK_SET)) {
 
556
        if(0 != fseeko(iterator->file, iterator->first_offset, SEEK_SET)) {
522
557
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
523
558
                return false;
524
559
        }
526
561
        if(!read_metadata_block_header_(iterator))
527
562
                return false;
528
563
 
529
 
        /* we ignore any error from ftell() and catch it in fseek() */
530
 
        while(ftell(iterator->file) + (long)iterator->length < iterator->offset[iterator->depth]) {
531
 
                if(0 != fseek(iterator->file, iterator->length, SEEK_CUR)) {
 
564
        /* we ignore any error from ftello() and catch it in fseeko() */
 
565
        while(ftello(iterator->file) + (off_t)iterator->length < iterator->offset[iterator->depth]) {
 
566
                if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) {
532
567
                        iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
533
568
                        return false;
534
569
                }
535
 
                this_offset = ftell(iterator->file);
 
570
                this_offset = ftello(iterator->file);
536
571
                if(!read_metadata_block_header_(iterator))
537
572
                        return false;
538
573
        }
567
602
                }
568
603
 
569
604
                /* back up to the beginning of the block data to stay consistent */
570
 
                if(0 != fseek(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
 
605
                if(0 != fseeko(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) {
571
606
                        iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
572
607
                        FLAC__metadata_object_delete(block);
573
608
                        return 0;
581
616
 
582
617
FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding)
583
618
{
584
 
        FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];)
 
619
        FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];)
585
620
        FLAC__bool ret;
586
621
 
587
622
        FLAC__ASSERT(0 != iterator);
608
643
                if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) {
609
644
                        ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last);
610
645
                        FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
611
 
                        FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
 
646
                        FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
612
647
                        return ret;
613
648
                }
614
649
                else {
615
650
                        ret = rewrite_whole_file_(iterator, block, /*append=*/false);
616
651
                        FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
617
 
                        FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
 
652
                        FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
618
653
                        return ret;
619
654
                }
620
655
        }
657
692
                        if(padding_leftover == 0) {
658
693
                                ret = write_metadata_block_stationary_(iterator, block);
659
694
                                FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
660
 
                                FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
 
695
                                FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
661
696
                                return ret;
662
697
                        }
663
698
                        else {
664
699
                                FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH);
665
700
                                ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last);
666
701
                                FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
667
 
                                FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
 
702
                                FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
668
703
                                return ret;
669
704
                        }
670
705
                }
671
706
                else {
672
707
                        ret = rewrite_whole_file_(iterator, block, /*append=*/false);
673
708
                        FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset);
674
 
                        FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH);
 
709
                        FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH);
675
710
                        return ret;
676
711
                }
677
712
        }
682
717
        unsigned padding_leftover = 0;
683
718
        FLAC__bool padding_is_last = false;
684
719
 
685
 
        FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
 
720
        FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;)
686
721
        FLAC__bool ret;
687
722
 
688
723
        FLAC__ASSERT(0 != iterator);
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);
741
776
                        return ret;
742
777
                }
743
778
                else {
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);
748
783
                        return ret;
749
784
                }
750
785
        }
751
786
        else {
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);
755
790
                return ret;
756
791
        }
757
792
}
758
793
 
759
794
FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding)
760
795
{
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];)
762
797
        FLAC__bool ret;
763
798
 
764
799
        if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) {
780
815
                FLAC__metadata_object_delete(padding);
781
816
                if(!FLAC__metadata_simple_iterator_prev(iterator))
782
817
                        return false;
783
 
                FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
784
 
                FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
 
818
                FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset);
 
819
                FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset);
785
820
                return true;
786
821
        }
787
822
        else {
788
823
                ret = rewrite_whole_file_(iterator, 0, /*append=*/false);
789
 
                FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset);
790
 
                FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset);
 
824
                FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset);
 
825
                FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset);
791
826
                return ret;
792
827
        }
793
828
}
808
843
 
809
844
struct FLAC__Metadata_Chain {
810
845
        char *filename; /* will be NULL if using callbacks */
 
846
        FLAC__bool is_ogg;
811
847
        FLAC__Metadata_Node *head;
812
848
        FLAC__Metadata_Node *tail;
813
849
        unsigned nodes;
814
850
        FLAC__Metadata_ChainStatus status;
815
 
        long first_offset, last_offset; /*@@@ 2G limit */
 
851
        off_t first_offset, last_offset;
816
852
        /*
817
853
         * This is the length of the chain initially read from the FLAC file.
818
854
         * it is used to compare against the current length to decide whether
819
855
         * or not the whole file has to be rewritten.
820
856
         */
821
 
        unsigned initial_length; /*@@@ 4G limit */
 
857
        off_t initial_length;
 
858
        /* @@@ hacky, these are currently only needed by ogg reader */
 
859
        FLAC__IOHandle handle;
 
860
        FLAC__IOCallback_Read read_cb;
822
861
};
823
862
 
824
863
struct FLAC__Metadata_Iterator {
846
885
};
847
886
 
848
887
 
849
 
static FLAC__Metadata_Node *node_new_()
 
888
static FLAC__Metadata_Node *node_new_(void)
850
889
{
851
890
        return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node));
852
891
}
864
903
        FLAC__ASSERT(0 != chain);
865
904
 
866
905
        chain->filename = 0;
 
906
        chain->is_ogg = false;
867
907
        chain->head = chain->tail = 0;
868
908
        chain->nodes = 0;
869
909
        chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
870
910
        chain->initial_length = 0;
 
911
        chain->read_cb = 0;
871
912
}
872
913
 
873
914
static void chain_clear_(FLAC__Metadata_Chain *chain)
937
978
        node_delete_(node);
938
979
}
939
980
 
940
 
static unsigned chain_calculate_length_(FLAC__Metadata_Chain *chain)
 
981
static off_t chain_calculate_length_(FLAC__Metadata_Chain *chain)
941
982
{
942
983
        const FLAC__Metadata_Node *node;
943
 
        unsigned length = 0;
 
984
        off_t length = 0;
944
985
        for(node = chain->head; node; node = node->next)
945
986
                length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
946
987
        return length;
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.
1021
1062
 */
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)
1023
1064
{
1024
 
        unsigned current_length = chain_calculate_length_(chain);
 
1065
        off_t current_length = chain_calculate_length_(chain);
1025
1066
 
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);
1033
1074
                }
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))) {
1052
1093
                }
1053
1094
                /* 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 */
1054
1095
                else if(current_length > chain->initial_length) {
1055
 
                        const unsigned delta = current_length - chain->initial_length;
 
1096
                        const off_t delta = current_length - chain->initial_length;
1056
1097
                        if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1057
1098
                                /* if the delta is exactly the size of the last padding block, remove the padding block */
1058
 
                                if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
 
1099
                                if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) {
1059
1100
                                        chain_delete_node_(chain, chain->tail);
1060
1101
                                        current_length = chain_calculate_length_(chain);
1061
1102
                                        FLAC__ASSERT(current_length == chain->initial_length);
1062
1103
                                }
1063
1104
                                /* if there is at least 'delta' bytes of padding, trim the padding down */
1064
 
                                else if(chain->tail->data->length >= delta) {
 
1105
                                else if((off_t)chain->tail->data->length >= delta) {
1065
1106
                                        chain->tail->data->length -= delta;
1066
1107
                                        current_length -= delta;
1067
1108
                                        FLAC__ASSERT(current_length == chain->initial_length);
1104
1145
                        chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1105
1146
                        return false;
1106
1147
                }
1107
 
                chain->first_offset = (long)pos;
 
1148
                chain->first_offset = (off_t)pos;
1108
1149
        }
1109
1150
 
1110
1151
        {
1149
1190
                        chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR;
1150
1191
                        return false;
1151
1192
                }
1152
 
                chain->last_offset = (long)pos;
1153
 
        }
 
1193
                chain->last_offset = (off_t)pos;
 
1194
        }
 
1195
 
 
1196
        chain->initial_length = chain_calculate_length_(chain);
 
1197
 
 
1198
        return true;
 
1199
}
 
1200
 
 
1201
FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
 
1202
{
 
1203
        FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
 
1204
        (void)decoder;
 
1205
        if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) {
 
1206
                *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle);
 
1207
                if(*bytes == 0)
 
1208
                        return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
 
1209
                else
 
1210
                        return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
 
1211
        }
 
1212
        else
 
1213
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
 
1214
}
 
1215
 
 
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)
 
1217
{
 
1218
        (void)decoder, (void)frame, (void)buffer, (void)client_data;
 
1219
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 
1220
}
 
1221
 
 
1222
static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 
1223
{
 
1224
        FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data;
 
1225
        FLAC__Metadata_Node *node;
 
1226
 
 
1227
        (void)decoder;
 
1228
 
 
1229
        node = node_new_();
 
1230
        if(0 == node) {
 
1231
                chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
 
1232
                return;
 
1233
        }
 
1234
 
 
1235
        node->data = FLAC__metadata_object_clone(metadata);
 
1236
        if(0 == node->data) {
 
1237
                node_delete_(node);
 
1238
                chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
 
1239
                return;
 
1240
        }
 
1241
 
 
1242
        chain_append_node_(chain, node);
 
1243
}
 
1244
 
 
1245
static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 
1246
{
 
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 */
 
1250
}
 
1251
 
 
1252
static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb)
 
1253
{
 
1254
        FLAC__StreamDecoder *decoder;
 
1255
 
 
1256
        FLAC__ASSERT(0 != chain);
 
1257
 
 
1258
        /* we assume we're already at the beginning of the file */
 
1259
 
 
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;
 
1264
                return false;
 
1265
        }
 
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 */
 
1270
                return false;
 
1271
        }
 
1272
 
 
1273
        chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
 
1274
 
 
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);
 
1279
                return false;
 
1280
        }
 
1281
 
 
1282
        FLAC__stream_decoder_delete(decoder);
 
1283
 
 
1284
        chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */
1154
1285
 
1155
1286
        chain->initial_length = chain_calculate_length_(chain);
1156
1287
 
1180
1311
                }
1181
1312
        }
1182
1313
 
1183
 
        /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
 
1314
        /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1184
1315
 
1185
1316
        chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
1186
1317
        return true;
1244
1375
                        return false;
1245
1376
                }
1246
1377
        }
1247
 
        /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
 
1378
        /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1248
1379
 
1249
1380
        /* copy the file postfix (everything after the metadata) */
1250
 
        if(0 != fseek(f, chain->last_offset, SEEK_SET)) {
 
1381
        if(0 != fseeko(f, chain->last_offset, SEEK_SET)) {
1251
1382
                cleanup_tempfile_(&tempfile, &tempfilename);
1252
1383
                chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1253
1384
                return false;
1293
1424
                        return false;
1294
1425
                }
1295
1426
        }
1296
 
        /*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/
 
1427
        /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/
1297
1428
 
1298
1429
        /* copy the file postfix (everything after the metadata) */
1299
1430
        if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) {
1308
1439
        return true;
1309
1440
}
1310
1441
 
1311
 
FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new()
 
1442
FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void)
1312
1443
{
1313
1444
        FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain));
1314
1445
 
1338
1469
        return status;
1339
1470
}
1340
1471
 
1341
 
FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
 
1472
static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg)
1342
1473
{
1343
1474
        FILE *file;
1344
1475
        FLAC__bool ret;
1353
1484
                return false;
1354
1485
        }
1355
1486
 
 
1487
        chain->is_ogg = is_ogg;
 
1488
 
1356
1489
        if(0 == (file = fopen(filename, "rb"))) {
1357
1490
                chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
1358
1491
                return false;
1359
1492
        }
1360
1493
 
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 */
 
1495
        ret = is_ogg?
 
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_)
 
1498
        ;
1363
1499
 
1364
1500
        fclose(file);
1365
1501
 
1366
1502
        return ret;
1367
1503
}
1368
1504
 
 
1505
FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
 
1506
{
 
1507
        return chain_read_(chain, filename, /*is_ogg=*/false);
 
1508
}
 
1509
 
 
1510
FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename)
 
1511
{
 
1512
        return chain_read_(chain, filename, /*is_ogg=*/true);
 
1513
}
 
1514
 
 
1515
static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg)
 
1516
{
 
1517
        FLAC__bool ret;
 
1518
 
 
1519
        FLAC__ASSERT(0 != chain);
 
1520
 
 
1521
        chain_clear_(chain);
 
1522
 
 
1523
        if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
 
1524
                chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
 
1525
                return false;
 
1526
        }
 
1527
 
 
1528
        chain->is_ogg = is_ogg;
 
1529
 
 
1530
        /* rewind */
 
1531
        if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
 
1532
                chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
 
1533
                return false;
 
1534
        }
 
1535
 
 
1536
        /* the function also sets chain->status for us */
 
1537
        ret = is_ogg?
 
1538
                chain_read_ogg_cb_(chain, handle, callbacks.read) :
 
1539
                chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell)
 
1540
        ;
 
1541
 
 
1542
        return ret;
 
1543
}
 
1544
 
1369
1545
FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1370
1546
{
1371
 
        FLAC__ASSERT(0 != chain);
1372
 
 
1373
 
        chain_clear_(chain);
1374
 
 
1375
 
        if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
1376
 
                chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
1377
 
                return false;
1378
 
        }
1379
 
 
1380
 
        /* rewind */
1381
 
        if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
1382
 
                chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
1383
 
                return false;
1384
 
        }
1385
 
 
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_ */
1388
 
 
1389
 
        return true;
 
1547
        return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false);
 
1548
}
 
1549
 
 
1550
FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
 
1551
{
 
1552
        return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true);
1390
1553
}
1391
1554
 
1392
1555
FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
1395
1558
         * but doesn't actually alter the chain.  Make sure to update the logic
1396
1559
         * here if chain_prepare_for_write_() changes.
1397
1560
         */
1398
 
        const unsigned current_length = chain_calculate_length_(chain);
 
1561
        const off_t current_length = chain_calculate_length_(chain);
1399
1562
 
1400
1563
        FLAC__ASSERT(0 != chain);
1401
1564
 
1404
1567
                if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING)
1405
1568
                        return false;
1406
1569
                /* if the metadata shrank more than 4 bytes then there's room to add another padding block */
1407
 
                else if(current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length)
 
1570
                else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length)
1408
1571
                        return false;
1409
1572
                /* 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 */
1410
1573
                else if(current_length > chain->initial_length) {
1411
 
                        const unsigned delta = current_length - chain->initial_length;
 
1574
                        const off_t delta = current_length - chain->initial_length;
1412
1575
                        if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
1413
1576
                                /* if the delta is exactly the size of the last padding block, remove the padding block */
1414
 
                                if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta)
 
1577
                                if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta)
1415
1578
                                        return false;
1416
1579
                                /* if there is at least 'delta' bytes of padding, trim the padding down */
1417
 
                                else if(chain->tail->data->length >= delta)
 
1580
                                else if((off_t)chain->tail->data->length >= delta)
1418
1581
                                        return false;
1419
1582
                        }
1420
1583
                }
1427
1590
{
1428
1591
        struct stat stats;
1429
1592
        const char *tempfile_path_prefix = 0;
1430
 
        unsigned current_length;
 
1593
        off_t current_length;
1431
1594
 
1432
1595
        FLAC__ASSERT(0 != chain);
1433
1596
 
 
1597
        if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
 
1598
                chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
 
1599
                return false;
 
1600
        }
 
1601
 
1434
1602
        if (0 == chain->filename) {
1435
1603
                chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1436
1604
                return false;
1471
1639
 
1472
1640
FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
1473
1641
{
1474
 
        unsigned current_length;
 
1642
        off_t current_length;
1475
1643
 
1476
1644
        FLAC__ASSERT(0 != chain);
1477
1645
 
 
1646
        if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
 
1647
                chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
 
1648
                return false;
 
1649
        }
 
1650
 
1478
1651
        if (0 != chain->filename) {
1479
1652
                chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1480
1653
                return false;
1503
1676
 
1504
1677
FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks)
1505
1678
{
1506
 
        unsigned current_length;
 
1679
        off_t current_length;
1507
1680
 
1508
1681
        FLAC__ASSERT(0 != chain);
1509
1682
 
 
1683
        if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */
 
1684
                chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR;
 
1685
                return false;
 
1686
        }
 
1687
 
1510
1688
        if (0 != chain->filename) {
1511
1689
                chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
1512
1690
                return false;
1594
1772
}
1595
1773
 
1596
1774
 
1597
 
FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new()
 
1775
FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void)
1598
1776
{
1599
1777
        FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator));
1600
1778
 
1873
2051
                        return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment);
1874
2052
                case FLAC__METADATA_TYPE_CUESHEET:
1875
2053
                        return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet);
 
2054
                case FLAC__METADATA_TYPE_PICTURE:
 
2055
                        return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture);
1876
2056
                default:
1877
2057
                        return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length);
1878
2058
        }
1904
2084
        return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
1905
2085
}
1906
2086
 
1907
 
 
1908
2087
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length)
1909
2088
{
1910
2089
        (void)block; /* nothing to do; we don't care about reading the padding bytes */
1969
2148
        const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
1970
2149
        FLAC__byte buffer[4]; /* magic number is asserted below */
1971
2150
 
1972
 
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
 
2151
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer));
1973
2152
 
1974
2153
        if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
1975
2154
                return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2001
2180
        const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2002
2181
        FLAC__byte buffer[4]; /* magic number is asserted below */
2003
2182
 
2004
 
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
 
2183
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer));
2005
2184
 
2006
2185
        if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string))))
2007
2186
                return status;
2139
2318
        return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
2140
2319
}
2141
2320
 
 
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)
 
2322
{
 
2323
        FLAC__byte buffer[sizeof(FLAC__uint32)];
 
2324
 
 
2325
        FLAC__ASSERT(0 != data);
 
2326
        FLAC__ASSERT(length_len%8 == 0);
 
2327
 
 
2328
        length_len /= 8; /* convert to bytes */
 
2329
 
 
2330
        FLAC__ASSERT(sizeof(buffer) >= length_len);
 
2331
 
 
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);
 
2335
 
 
2336
        if(0 != *data)
 
2337
                free(*data);
 
2338
 
 
2339
        if(0 == (*data = (FLAC__byte*)malloc(*length+1)))
 
2340
                return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
 
2341
 
 
2342
        if(*length > 0) {
 
2343
                if(read_cb(*data, 1, *length, handle) != *length)
 
2344
                        return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
 
2345
        }
 
2346
 
 
2347
        (*data)[*length] = '\0';
 
2348
 
 
2349
        return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 
2350
}
 
2351
 
 
2352
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block)
 
2353
{
 
2354
        FLAC__Metadata_SimpleIteratorStatus status;
 
2355
        FLAC__byte buffer[4]; /* asserted below that this is big enough */
 
2356
        FLAC__uint32 len;
 
2357
 
 
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);
 
2363
 
 
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);
 
2369
 
 
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)
 
2371
                return status;
 
2372
 
 
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)
 
2374
                return status;
 
2375
 
 
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);
 
2381
 
 
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);
 
2387
 
 
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);
 
2393
 
 
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);
 
2399
 
 
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)
 
2402
                return status;
 
2403
 
 
2404
        return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 
2405
}
 
2406
 
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)
2143
2408
{
2144
2409
        if(block_length == 0) {
2215
2480
                        return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment);
2216
2481
                case FLAC__METADATA_TYPE_CUESHEET:
2217
2482
                        return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet);
 
2483
                case FLAC__METADATA_TYPE_PICTURE:
 
2484
                        return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture);
2218
2485
                default:
2219
2486
                        return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length);
2220
2487
        }
2307
2574
        const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
2308
2575
        FLAC__byte buffer[4]; /* magic number is asserted below */
2309
2576
 
2310
 
        FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == 4);
 
2577
        FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer));
2311
2578
 
2312
2579
        pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
2313
2580
        if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
2424
2691
        return true;
2425
2692
}
2426
2693
 
 
2694
FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block)
 
2695
{
 
2696
        unsigned len;
 
2697
        size_t slen;
 
2698
        FLAC__byte buffer[4]; /* magic number is asserted below */
 
2699
 
 
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);
 
2716
 
 
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)
 
2720
                return false;
 
2721
 
 
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)
 
2726
                return false;
 
2727
        if(write_cb(block->mime_type, 1, slen, handle) != slen)
 
2728
                return false;
 
2729
 
 
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)
 
2734
                return false;
 
2735
        if(write_cb(block->description, 1, slen, handle) != slen)
 
2736
                return false;
 
2737
 
 
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)
 
2741
                return false;
 
2742
 
 
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)
 
2746
                return false;
 
2747
 
 
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)
 
2751
                return false;
 
2752
 
 
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)
 
2756
                return false;
 
2757
 
 
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)
 
2761
                return false;
 
2762
        if(write_cb(block->data, 1, block->data_length, handle) != block->data_length)
 
2763
                return false;
 
2764
 
 
2765
        return true;
 
2766
}
 
2767
 
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)
2428
2769
{
2429
2770
        if(write_cb(block->data, 1, block_length, handle) != block_length)
2434
2775
 
2435
2776
FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block)
2436
2777
{
2437
 
        if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
 
2778
        if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2438
2779
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2439
2780
                return false;
2440
2781
        }
2445
2786
        if(!write_metadata_block_data_(iterator->file, &iterator->status, block))
2446
2787
                return false;
2447
2788
 
2448
 
        if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
 
2789
        if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2449
2790
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2450
2791
                return false;
2451
2792
        }
2457
2798
{
2458
2799
        FLAC__StreamMetadata *padding;
2459
2800
 
2460
 
        if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
 
2801
        if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2461
2802
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2462
2803
                return false;
2463
2804
        }
2488
2829
 
2489
2830
        FLAC__metadata_object_delete(padding);
2490
2831
 
2491
 
        if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
 
2832
        if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2492
2833
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2493
2834
                return false;
2494
2835
        }
2501
2842
        FILE *tempfile;
2502
2843
        char *tempfilename;
2503
2844
        int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */
2504
 
        long fixup_is_last_flag_offset = -1;
 
2845
        off_t fixup_is_last_flag_offset = -1;
2505
2846
 
2506
2847
        FLAC__ASSERT(0 != block || append == false);
2507
2848
 
2558
2899
{
2559
2900
        FLAC__ASSERT(iterator->depth > 0);
2560
2901
        iterator->depth--;
2561
 
        if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
 
2902
        if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
2562
2903
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2563
2904
                return false;
2564
2905
        }
2578
2919
        size_t n;
2579
2920
        unsigned i;
2580
2921
 
2581
 
        FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
 
2922
        FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer));
2582
2923
 
2583
2924
        /* skip any id3v2 tag */
2584
2925
        errno = 0;
2629
2970
 
2630
2971
FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append)
2631
2972
{
2632
 
        const long offset_end = append? iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length : iterator->offset[iterator->depth];
 
2973
        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];
2633
2974
 
2634
 
        if(0 != fseek(iterator->file, 0, SEEK_SET)) {
 
2975
        if(0 != fseeko(iterator->file, 0, SEEK_SET)) {
2635
2976
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2636
2977
                return false;
2637
2978
        }
2647
2988
        return true;
2648
2989
}
2649
2990
 
2650
 
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)
 
2991
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)
2651
2992
{
2652
 
        long save_offset = iterator->offset[iterator->depth]; /*@@@ 2G limit */
 
2993
        off_t save_offset = iterator->offset[iterator->depth];
2653
2994
        FLAC__ASSERT(0 != *tempfile);
2654
2995
 
2655
 
        if(0 != fseek(iterator->file, save_offset + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length, SEEK_SET)) {
 
2996
        if(0 != fseeko(iterator->file, save_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length, SEEK_SET)) {
2656
2997
                cleanup_tempfile_(tempfile, tempfilename);
2657
2998
                iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2658
2999
                return false;
2671
3012
                 */
2672
3013
                /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */
2673
3014
                FLAC__byte x;
2674
 
                if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
 
3015
                if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2675
3016
                        cleanup_tempfile_(tempfile, tempfilename);
2676
3017
                        iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2677
3018
                        return false;
2689
3030
                        FLAC__ASSERT(!(x & 0x80));
2690
3031
                        x |= 0x80;
2691
3032
                }
2692
 
                if(0 != fseek(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
 
3033
                if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) {
2693
3034
                        cleanup_tempfile_(tempfile, tempfilename);
2694
3035
                        iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
2695
3036
                        return false;
2712
3053
        if(!simple_iterator_prime_input_(iterator, !iterator->is_writable))
2713
3054
                return false;
2714
3055
        if(backup) {
2715
 
                while(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length < save_offset)
 
3056
                while(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length < save_offset)
2716
3057
                        if(!FLAC__metadata_simple_iterator_next(iterator))
2717
3058
                                return false;
2718
3059
                return true;
2726
3067
        }
2727
3068
}
2728
3069
 
2729
 
FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, unsigned bytes/*@@@ 4G limit*/, FLAC__Metadata_SimpleIteratorStatus *status)
 
3070
FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status)
2730
3071
{
2731
3072
        FLAC__byte buffer[8192];
2732
 
        unsigned n;
 
3073
        size_t n;
2733
3074
 
 
3075
        FLAC__ASSERT(bytes >= 0);
2734
3076
        while(bytes > 0) {
2735
 
                n = min(sizeof(buffer), bytes);
 
3077
                n = min(sizeof(buffer), (size_t)bytes);
2736
3078
                if(fread(buffer, 1, n, file) != n) {
2737
3079
                        *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2738
3080
                        return false;
2747
3089
        return true;
2748
3090
}
2749
3091
 
2750
 
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)
 
3092
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)
2751
3093
{
2752
3094
        FLAC__byte buffer[8192];
2753
 
        unsigned n;
 
3095
        size_t n;
2754
3096
 
 
3097
        FLAC__ASSERT(bytes >= 0);
2755
3098
        while(bytes > 0) {
2756
 
                n = min(sizeof(buffer), bytes);
 
3099
                n = min(sizeof(buffer), (size_t)bytes);
2757
3100
                if(read_cb(buffer, 1, n, handle) != n) {
2758
3101
                        *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
2759
3102
                        return false;
2856
3199
        (void)fclose(*tempfile);
2857
3200
        *tempfile = 0;
2858
3201
 
2859
 
#if defined _MSC_VER || defined __MINGW32__
 
3202
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__
 
3203
        /* on some flavors of windows, rename() will fail if the destination already exists */
2860
3204
        if(unlink(filename) < 0) {
2861
3205
                cleanup_tempfile_(tempfile, tempfilename);
2862
3206
                *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR;
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);
2914
3258
#endif
2915
3259
}
2916
3260
 
2917
 
/* @@@ WATCHOUT @@@
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
2920
 
 * 2 gigabytes.
2921
 
 */
2922
3261
int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
2923
3262
{
2924
 
        FLAC__ASSERT(offset <= 0x7fffffff);
2925
 
        return fseek((FILE*)handle, (long)offset, whence);
 
3263
        return fseeko((FILE*)handle, (off_t)offset, whence);
2926
3264
}
2927
3265
 
2928
3266
FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle)
2929
3267
{
2930
 
        return (long)ftell((FILE*)handle);
 
3268
        return ftello((FILE*)handle);
2931
3269
}
2932
3270
 
2933
3271
FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status)