1From 078f997f8fd7ddba46780961af0c92820b25a4e3 Mon Sep 17 00:00:00 2001
2From: Urs Fleisch <ufleisch@users.sourceforge.net>
3Date: Sun, 19 Apr 2020 11:13:55 +0200
4Subject: Support large files over 2GB
5
6Backport of 4dcf0b41c687292e7b1263a679921c157ae2c22a
7b01f45e141afa6a89aea319a2783f177e202fa1d
8https://github.com/taglib/taglib/pull/77
9
10diff --git a/taglib/ape/apefile.cpp b/taglib/ape/apefile.cpp
11index a10c1f64..290836bd 100644
12--- a/taglib/ape/apefile.cpp
13+++ b/taglib/ape/apefile.cpp
14@@ -69,13 +69,13 @@ public:
15     delete properties;
16   }
17
18-  long APELocation;
19+  offset_t APELocation;
20   long APESize;
21
22-  long ID3v1Location;
23+  offset_t ID3v1Location;
24
25   ID3v2::Header *ID3v2Header;
26-  long ID3v2Location;
27+  offset_t ID3v2Location;
28   long ID3v2Size;
29
30   TagUnion tag;
31@@ -292,7 +292,7 @@ void APE::File::read(bool readProperties)
32
33   if(readProperties) {
34
35-    long streamLength;
36+    offset_t streamLength;
37
38     if(d->APELocation >= 0)
39       streamLength = d->APELocation;
40diff --git a/taglib/ape/apeproperties.cpp b/taglib/ape/apeproperties.cpp
41index dee7e8c0..5a43445e 100644
42--- a/taglib/ape/apeproperties.cpp
43+++ b/taglib/ape/apeproperties.cpp
44@@ -70,7 +70,7 @@ APE::Properties::Properties(File *, ReadStyle style) :
45   debug("APE::Properties::Properties() -- This constructor is no longer used.");
46 }
47
48-APE::Properties::Properties(File *file, long streamLength, ReadStyle style) :
49+APE::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
50   AudioProperties(style),
51   d(new PropertiesPrivate())
52 {
53@@ -142,10 +142,10 @@ namespace
54   }
55 }
56
57-void APE::Properties::read(File *file, long streamLength)
58+void APE::Properties::read(File *file, offset_t streamLength)
59 {
60   // First, we assume that the file pointer is set at the first descriptor.
61-  long offset = file->tell();
62+  offset_t offset = file->tell();
63   int version = headerVersion(file->readBlock(6));
64
65   // Next, we look for the descriptor.
66diff --git a/taglib/ape/apeproperties.h b/taglib/ape/apeproperties.h
67index ebbf949b..d527815f 100644
68--- a/taglib/ape/apeproperties.h
69+++ b/taglib/ape/apeproperties.h
70@@ -61,7 +61,7 @@ namespace TagLib {
71        * Create an instance of APE::Properties with the data read from the
72        * APE::File \a file.
73        */
74-      Properties(File *file, long streamLength, ReadStyle style = Average);
75+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
76
77       /*!
78        * Destroys this APE::Properties instance.
79@@ -129,7 +129,7 @@ namespace TagLib {
80       Properties(const Properties &);
81       Properties &operator=(const Properties &);
82
83-      void read(File *file, long streamLength);
84+      void read(File *file, offset_t streamLength);
85
86       void analyzeCurrent(File *file);
87       void analyzeOld(File *file);
88diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp
89index 79e1d5cc..15a9c4ea 100644
90--- a/taglib/ape/apetag.cpp
91+++ b/taglib/ape/apetag.cpp
92@@ -80,7 +80,7 @@ public:
93     footerLocation(0) {}
94
95   File *file;
96-  long footerLocation;
97+  offset_t footerLocation;
98
99   Footer footer;
100   ItemListMap itemListMap;
101@@ -96,7 +96,7 @@ APE::Tag::Tag() :
102 {
103 }
104
105-APE::Tag::Tag(TagLib::File *file, long footerLocation) :
106+APE::Tag::Tag(TagLib::File *file, offset_t footerLocation) :
107   TagLib::Tag(),
108   d(new TagPrivate())
109 {
110diff --git a/taglib/ape/apetag.h b/taglib/ape/apetag.h
111index f4d4fba6..b5a2eb87 100644
112--- a/taglib/ape/apetag.h
113+++ b/taglib/ape/apetag.h
114@@ -66,7 +66,7 @@ namespace TagLib {
115        * Create an APE tag and parse the data in \a file with APE footer at
116        * \a tagOffset.
117        */
118-      Tag(TagLib::File *file, long footerLocation);
119+      Tag(TagLib::File *file, offset_t footerLocation);
120
121       /*!
122        * Destroys this Tag instance.
123diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp
124index ada215db..3f4accab 100644
125--- a/taglib/flac/flacfile.cpp
126+++ b/taglib/flac/flacfile.cpp
127@@ -79,10 +79,10 @@ public:
128   }
129
130   const ID3v2::FrameFactory *ID3v2FrameFactory;
131-  long ID3v2Location;
132+  offset_t ID3v2Location;
133   long ID3v2OriginalSize;
134
135-  long ID3v1Location;
136+  offset_t ID3v1Location;
137
138   TagUnion tag;
139
140@@ -90,8 +90,8 @@ public:
141   ByteVector xiphCommentData;
142   BlockList blocks;
143
144-  long flacStart;
145-  long streamStart;
146+  offset_t flacStart;
147+  offset_t streamStart;
148   bool scanned;
149 };
150
151@@ -341,7 +341,7 @@ ByteVector FLAC::File::streamInfoData()
152   return ByteVector();
153 }
154
155-long FLAC::File::streamLength()
156+offset_t FLAC::File::streamLength()
157 {
158   debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
159   return 0;
160@@ -456,7 +456,7 @@ void FLAC::File::read(bool readProperties)
161
162     const ByteVector infoData = d->blocks.front()->render();
163
164-    long streamLength;
165+    offset_t streamLength;
166
167     if(d->ID3v1Location >= 0)
168       streamLength = d->ID3v1Location - d->streamStart;
169@@ -477,7 +477,7 @@ void FLAC::File::scan()
170   if(!isValid())
171     return;
172
173-  long nextBlockOffset;
174+  offset_t nextBlockOffset;
175
176   if(d->ID3v2Location >= 0)
177     nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
178diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h
179index 1b8654eb..9a2422f2 100644
180--- a/taglib/flac/flacfile.h
181+++ b/taglib/flac/flacfile.h
182@@ -256,7 +256,7 @@ namespace TagLib {
183        *
184        * \deprecated Always returns zero.
185        */
186-      TAGLIB_DEPRECATED long streamLength();  // BIC: remove
187+      TAGLIB_DEPRECATED offset_t streamLength();  // BIC: remove
188
189       /*!
190        * Returns a list of pictures attached to the FLAC file.
191diff --git a/taglib/flac/flacproperties.cpp b/taglib/flac/flacproperties.cpp
192index b947f039..a798940a 100644
193--- a/taglib/flac/flacproperties.cpp
194+++ b/taglib/flac/flacproperties.cpp
195@@ -55,7 +55,7 @@ public:
196 // public members
197 ////////////////////////////////////////////////////////////////////////////////
198
199-FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
200+FLAC::Properties::Properties(ByteVector data, offset_t streamLength, ReadStyle style) :
201   AudioProperties(style),
202   d(new PropertiesPrivate())
203 {
204@@ -128,7 +128,7 @@ ByteVector FLAC::Properties::signature() const
205 // private members
206 ////////////////////////////////////////////////////////////////////////////////
207
208-void FLAC::Properties::read(const ByteVector &data, long streamLength)
209+void FLAC::Properties::read(const ByteVector &data, offset_t streamLength)
210 {
211   if(data.size() < 18) {
212     debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
213diff --git a/taglib/flac/flacproperties.h b/taglib/flac/flacproperties.h
214index 743e5872..75e8ecb4 100644
215--- a/taglib/flac/flacproperties.h
216+++ b/taglib/flac/flacproperties.h
217@@ -50,7 +50,7 @@ namespace TagLib {
218        * ByteVector \a data.
219        */
220        // BIC: switch to const reference
221-      Properties(ByteVector data, long streamLength, ReadStyle style = Average);
222+      Properties(ByteVector data, offset_t streamLength, ReadStyle style = Average);
223
224       /*!
225        * Create an instance of FLAC::Properties with the data read from the
226@@ -137,7 +137,7 @@ namespace TagLib {
227       Properties(const Properties &);
228       Properties &operator=(const Properties &);
229
230-      void read(const ByteVector &data, long streamLength);
231+      void read(const ByteVector &data, offset_t streamLength);
232
233       class PropertiesPrivate;
234       PropertiesPrivate *d;
235diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp
236index 20709212..bff3ab46 100644
237--- a/taglib/mp4/mp4atom.cpp
238+++ b/taglib/mp4/mp4atom.cpp
239@@ -156,7 +156,7 @@ MP4::Atoms::Atoms(File *file)
240   atoms.setAutoDelete(true);
241
242   file->seek(0, File::End);
243-  long end = file->tell();
244+  offset_t end = file->tell();
245   file->seek(0);
246   while(file->tell() + 8 <= end) {
247     MP4::Atom *atom = new MP4::Atom(file);
248diff --git a/taglib/mp4/mp4atom.h b/taglib/mp4/mp4atom.h
249index cbb0d10a..53bc16a6 100644
250--- a/taglib/mp4/mp4atom.h
251+++ b/taglib/mp4/mp4atom.h
252@@ -82,8 +82,8 @@ namespace TagLib {
253       Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
254       bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
255       AtomList findall(const char *name, bool recursive = false);
256-      long offset;
257-      long length;
258+      offset_t offset;
259+      offset_t length;
260       TagLib::ByteVector name;
261       AtomList children;
262     private:
263diff --git a/taglib/mp4/mp4tag.cpp b/taglib/mp4/mp4tag.cpp
264index 87ac1852..3d5b2113 100644
265--- a/taglib/mp4/mp4tag.cpp
266+++ b/taglib/mp4/mp4tag.cpp
267@@ -570,7 +570,7 @@ MP4::Tag::updateParents(const AtomList &path, long delta, int ignore)
268 }
269
270 void
271-MP4::Tag::updateOffsets(long delta, long offset)
272+MP4::Tag::updateOffsets(long delta, offset_t offset)
273 {
274   MP4::Atom *moov = d->atoms->find("moov");
275   if(moov) {
276@@ -654,7 +654,7 @@ MP4::Tag::saveNew(ByteVector data)
277     data = renderAtom("udta", data);
278   }
279
280-  long offset = path.back()->offset + 8;
281+  offset_t offset = path.back()->offset + 8;
282   d->file->insert(data, offset, 0);
283
284   updateParents(path, data.size());
285@@ -672,8 +672,8 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
286   AtomList::ConstIterator it = path.end();
287
288   MP4::Atom *ilst = *(--it);
289-  long offset = ilst->offset;
290-  long length = ilst->length;
291+  offset_t offset = ilst->offset;
292+  offset_t length = ilst->length;
293
294   MP4::Atom *meta = *(--it);
295   AtomList::ConstIterator index = meta->children.find(ilst);
296diff --git a/taglib/mp4/mp4tag.h b/taglib/mp4/mp4tag.h
297index ccee8e06..026dd743 100644
298--- a/taglib/mp4/mp4tag.h
299+++ b/taglib/mp4/mp4tag.h
300@@ -146,7 +146,7 @@ namespace TagLib {
301         ByteVector renderCovr(const ByteVector &name, const Item &item) const;
302
303         void updateParents(const AtomList &path, long delta, int ignore = 0);
304-        void updateOffsets(long delta, long offset);
305+        void updateOffsets(long delta, offset_t offset);
306
307         void saveNew(ByteVector data);
308         void saveExisting(ByteVector data, const AtomList &path);
309diff --git a/taglib/mpc/mpcfile.cpp b/taglib/mpc/mpcfile.cpp
310index 0ffaf893..0e36a1f8 100644
311--- a/taglib/mpc/mpcfile.cpp
312+++ b/taglib/mpc/mpcfile.cpp
313@@ -61,13 +61,13 @@ public:
314     delete properties;
315   }
316
317-  long APELocation;
318+  offset_t APELocation;
319   long APESize;
320
321-  long ID3v1Location;
322+  offset_t ID3v1Location;
323
324   ID3v2::Header *ID3v2Header;
325-  long ID3v2Location;
326+  offset_t ID3v2Location;
327   long ID3v2Size;
328
329   TagUnion tag;
330@@ -310,7 +310,7 @@ void MPC::File::read(bool readProperties)
331
332   if(readProperties) {
333
334-    long streamLength;
335+    offset_t streamLength;
336
337     if(d->APELocation >= 0)
338       streamLength = d->APELocation;
339diff --git a/taglib/mpc/mpcproperties.cpp b/taglib/mpc/mpcproperties.cpp
340index 21de6d49..809165d9 100644
341--- a/taglib/mpc/mpcproperties.cpp
342+++ b/taglib/mpc/mpcproperties.cpp
343@@ -66,14 +66,14 @@ public:
344 // public members
345 ////////////////////////////////////////////////////////////////////////////////
346
347-MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
348+MPC::Properties::Properties(const ByteVector &data, offset_t streamLength, ReadStyle style) :
349   AudioProperties(style),
350   d(new PropertiesPrivate())
351 {
352   readSV7(data, streamLength);
353 }
354
355-MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
356+MPC::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
357   AudioProperties(style),
358   d(new PropertiesPrivate())
359 {
360@@ -203,7 +203,7 @@ namespace
361   const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
362 }
363
364-void MPC::Properties::readSV8(File *file, long streamLength)
365+void MPC::Properties::readSV8(File *file, offset_t streamLength)
366 {
367   bool readSH = false, readRG = false;
368
369@@ -295,7 +295,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
370   }
371 }
372
373-void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
374+void MPC::Properties::readSV7(const ByteVector &data, offset_t streamLength)
375 {
376   if(data.startsWith("MP+")) {
377     d->version = data[3] & 15;
378diff --git a/taglib/mpc/mpcproperties.h b/taglib/mpc/mpcproperties.h
379index 9a902dc9..439de74e 100644
380--- a/taglib/mpc/mpcproperties.h
381+++ b/taglib/mpc/mpcproperties.h
382@@ -53,13 +53,13 @@ namespace TagLib {
383        *
384        * This constructor is deprecated. It only works for MPC version up to 7.
385        */
386-      Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
387+      Properties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
388
389       /*!
390        * Create an instance of MPC::Properties with the data read directly
391        * from a MPC::File.
392        */
393-      Properties(File *file, long streamLength, ReadStyle style = Average);
394+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
395
396       /*!
397        * Destroys this MPC::Properties instance.
398@@ -146,8 +146,8 @@ namespace TagLib {
399       Properties(const Properties &);
400       Properties &operator=(const Properties &);
401
402-      void readSV7(const ByteVector &data, long streamLength);
403-      void readSV8(File *file, long streamLength);
404+      void readSV7(const ByteVector &data, offset_t streamLength);
405+      void readSV8(File *file, offset_t streamLength);
406
407       class PropertiesPrivate;
408       PropertiesPrivate *d;
409diff --git a/taglib/mpeg/id3v1/id3v1tag.cpp b/taglib/mpeg/id3v1/id3v1tag.cpp
410index ca930411..4d26b3a4 100644
411--- a/taglib/mpeg/id3v1/id3v1tag.cpp
412+++ b/taglib/mpeg/id3v1/id3v1tag.cpp
413@@ -48,7 +48,7 @@ public:
414     genre(255) {}
415
416   File *file;
417-  long tagOffset;
418+  offset_t tagOffset;
419
420   String title;
421   String artist;
422@@ -90,7 +90,7 @@ ID3v1::Tag::Tag() :
423 {
424 }
425
426-ID3v1::Tag::Tag(File *file, long tagOffset) :
427+ID3v1::Tag::Tag(File *file, offset_t tagOffset) :
428   TagLib::Tag(),
429   d(new TagPrivate())
430 {
431diff --git a/taglib/mpeg/id3v1/id3v1tag.h b/taglib/mpeg/id3v1/id3v1tag.h
432index b61f06af..55ab63ff 100644
433--- a/taglib/mpeg/id3v1/id3v1tag.h
434+++ b/taglib/mpeg/id3v1/id3v1tag.h
435@@ -114,7 +114,7 @@ namespace TagLib {
436        * Create an ID3v1 tag and parse the data in \a file starting at
437        * \a tagOffset.
438        */
439-      Tag(File *file, long tagOffset);
440+      Tag(File *file, offset_t tagOffset);
441
442       /*!
443        * Destroys this Tag instance.
444diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp
445index 54dddf72..cec886b9 100644
446--- a/taglib/mpeg/id3v2/id3v2tag.cpp
447+++ b/taglib/mpeg/id3v2/id3v2tag.cpp
448@@ -88,7 +88,7 @@ public:
449   const FrameFactory *factory;
450
451   File *file;
452-  long tagOffset;
453+  offset_t tagOffset;
454
455   Header header;
456   ExtendedHeader *extendedHeader;
457@@ -126,7 +126,7 @@ ID3v2::Tag::Tag() :
458   d->factory = FrameFactory::instance();
459 }
460
461-ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
462+ID3v2::Tag::Tag(File *file, offset_t tagOffset, const FrameFactory *factory) :
463   TagLib::Tag(),
464   d(new TagPrivate())
465 {
466diff --git a/taglib/mpeg/id3v2/id3v2tag.h b/taglib/mpeg/id3v2/id3v2tag.h
467index 74d1df1e..60b5c2e8 100644
468--- a/taglib/mpeg/id3v2/id3v2tag.h
469+++ b/taglib/mpeg/id3v2/id3v2tag.h
470@@ -146,7 +146,7 @@ namespace TagLib {
471        *
472        * \see FrameFactory
473        */
474-      Tag(File *file, long tagOffset,
475+      Tag(File *file, offset_t tagOffset,
476           const FrameFactory *factory = FrameFactory::instance());
477
478       /*!
479diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp
480index a2ce02a7..5212760d 100644
481--- a/taglib/mpeg/mpegfile.cpp
482+++ b/taglib/mpeg/mpegfile.cpp
483@@ -63,13 +63,13 @@ public:
484
485   const ID3v2::FrameFactory *ID3v2FrameFactory;
486
487-  long ID3v2Location;
488+  offset_t ID3v2Location;
489   long ID3v2OriginalSize;
490
491-  long APELocation;
492+  offset_t APELocation;
493   long APEOriginalSize;
494
495-  long ID3v1Location;
496+  offset_t ID3v1Location;
497
498   TagUnion tag;
499
500@@ -105,13 +105,13 @@ bool MPEG::File::isSupported(IOStream *stream)
501   // MPEG frame headers are really confusing with irrelevant binary data.
502   // So we check if a frame header is really valid.
503
504-  long headerOffset;
505+  offset_t headerOffset;
506   const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true, &headerOffset);
507
508   if(buffer.isEmpty())
509       return false;
510
511-  const long originalPosition = stream->tell();
512+  const offset_t originalPosition = stream->tell();
513   AdapterFile file(stream);
514
515   for(unsigned int i = 0; i < buffer.size() - 1; ++i) {
516@@ -406,7 +406,7 @@ void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
517   d->ID3v2FrameFactory = factory;
518 }
519
520-long MPEG::File::nextFrameOffset(long position)
521+offset_t MPEG::File::nextFrameOffset(offset_t position)
522 {
523   ByteVector frameSyncBytes(2, '\0');
524
525@@ -430,7 +430,7 @@ long MPEG::File::nextFrameOffset(long position)
526   }
527 }
528
529-long MPEG::File::previousFrameOffset(long position)
530+offset_t MPEG::File::previousFrameOffset(offset_t position)
531 {
532   ByteVector frameSyncBytes(2, '\0');
533
534@@ -455,7 +455,7 @@ long MPEG::File::previousFrameOffset(long position)
535   return -1;
536 }
537
538-long MPEG::File::firstFrameOffset()
539+offset_t MPEG::File::firstFrameOffset()
540 {
541   long position = 0;
542
543@@ -465,9 +465,9 @@ long MPEG::File::firstFrameOffset()
544   return nextFrameOffset(position);
545 }
546
547-long MPEG::File::lastFrameOffset()
548+offset_t MPEG::File::lastFrameOffset()
549 {
550-  long position;
551+  offset_t position;
552
553   if(hasAPETag())
554     position = d->APELocation - 1;
555@@ -535,7 +535,7 @@ void MPEG::File::read(bool readProperties)
556   ID3v1Tag(true);
557 }
558
559-long MPEG::File::findID3v2()
560+offset_t MPEG::File::findID3v2()
561 {
562   if(!isValid())
563     return -1;
564diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h
565index 3fcb7272..685f5054 100644
566--- a/taglib/mpeg/mpegfile.h
567+++ b/taglib/mpeg/mpegfile.h
568@@ -322,24 +322,24 @@ namespace TagLib {
569       /*!
570        * Returns the position in the file of the first MPEG frame.
571        */
572-      long firstFrameOffset();
573+      offset_t firstFrameOffset();
574
575       /*!
576        * Returns the position in the file of the next MPEG frame,
577        * using the current position as start
578        */
579-      long nextFrameOffset(long position);
580+      offset_t nextFrameOffset(offset_t position);
581
582       /*!
583        * Returns the position in the file of the previous MPEG frame,
584        * using the current position as start
585        */
586-      long previousFrameOffset(long position);
587+      offset_t previousFrameOffset(offset_t position);
588
589       /*!
590        * Returns the position in the file of the last MPEG frame.
591        */
592-      long lastFrameOffset();
593+      offset_t lastFrameOffset();
594
595       /*!
596        * Returns whether or not the file on disk actually has an ID3v1 tag.
597@@ -376,7 +376,7 @@ namespace TagLib {
598       File &operator=(const File &);
599
600       void read(bool readProperties);
601-      long findID3v2();
602+      offset_t findID3v2();
603
604       class FilePrivate;
605       FilePrivate *d;
606diff --git a/taglib/mpeg/mpegheader.cpp b/taglib/mpeg/mpegheader.cpp
607index 5a5015d6..b9405008 100644
608--- a/taglib/mpeg/mpegheader.cpp
609+++ b/taglib/mpeg/mpegheader.cpp
610@@ -75,7 +75,7 @@ MPEG::Header::Header(const ByteVector &data) :
611   debug("MPEG::Header::Header() - This constructor is no longer used.");
612 }
613
614-MPEG::Header::Header(File *file, long offset, bool checkLength) :
615+MPEG::Header::Header(File *file, offset_t offset, bool checkLength) :
616   d(new HeaderPrivate())
617 {
618   parse(file, offset, checkLength);
619@@ -170,7 +170,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h)
620 // private members
621 ////////////////////////////////////////////////////////////////////////////////
622
623-void MPEG::Header::parse(File *file, long offset, bool checkLength)
624+void MPEG::Header::parse(File *file, offset_t offset, bool checkLength)
625 {
626   file->seek(offset);
627   const ByteVector data = file->readBlock(4);
628diff --git a/taglib/mpeg/mpegheader.h b/taglib/mpeg/mpegheader.h
629index ca51184c..3fb214e5 100644
630--- a/taglib/mpeg/mpegheader.h
631+++ b/taglib/mpeg/mpegheader.h
632@@ -61,7 +61,7 @@ namespace TagLib {
633        * check if the frame length is parsed and calculated correctly.  So it's
634        * suitable for seeking for the first valid frame.
635        */
636-      Header(File *file, long offset, bool checkLength = true);
637+      Header(File *file, offset_t offset, bool checkLength = true);
638
639       /*!
640        * Does a shallow copy of \a h.
641@@ -167,7 +167,7 @@ namespace TagLib {
642       Header &operator=(const Header &h);
643
644     private:
645-      void parse(File *file, long offset, bool checkLength);
646+      void parse(File *file, offset_t offset, bool checkLength);
647
648       class HeaderPrivate;
649       HeaderPrivate *d;
650diff --git a/taglib/mpeg/mpegproperties.cpp b/taglib/mpeg/mpegproperties.cpp
651index 5eec84f7..d66f8ab1 100644
652--- a/taglib/mpeg/mpegproperties.cpp
653+++ b/taglib/mpeg/mpegproperties.cpp
654@@ -157,7 +157,7 @@ void MPEG::Properties::read(File *file)
655 {
656   // Only the first valid frame is required if we have a VBR header.
657
658-  const long firstFrameOffset = file->firstFrameOffset();
659+  const offset_t firstFrameOffset = file->firstFrameOffset();
660   if(firstFrameOffset < 0) {
661     debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
662     return;
663@@ -197,14 +197,14 @@ void MPEG::Properties::read(File *file)
664
665     // Look for the last MPEG audio frame to calculate the stream length.
666
667-    const long lastFrameOffset = file->lastFrameOffset();
668+    const offset_t lastFrameOffset = file->lastFrameOffset();
669     if(lastFrameOffset < 0) {
670       debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
671     }
672     else
673     {
674       const Header lastHeader(file, lastFrameOffset, false);
675-      const long streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
676+      const offset_t streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
677       if (streamLength > 0)
678         d->length = static_cast<int>(streamLength * 8.0 / d->bitrate + 0.5);
679     }
680diff --git a/taglib/ogg/flac/oggflacfile.cpp b/taglib/ogg/flac/oggflacfile.cpp
681index 07ea9dcc..5c2f95c6 100644
682--- a/taglib/ogg/flac/oggflacfile.cpp
683+++ b/taglib/ogg/flac/oggflacfile.cpp
684@@ -58,8 +58,8 @@ public:
685   Properties *properties;
686   ByteVector streamInfoData;
687   ByteVector xiphCommentData;
688-  long streamStart;
689-  long streamLength;
690+  offset_t streamStart;
691+  offset_t streamLength;
692   bool scanned;
693
694   bool hasXiphComment;
695@@ -206,7 +206,7 @@ ByteVector Ogg::FLAC::File::xiphCommentData()
696   return d->xiphCommentData;
697 }
698
699-long Ogg::FLAC::File::streamLength()
700+offset_t Ogg::FLAC::File::streamLength()
701 {
702   scan();
703   return d->streamLength;
704@@ -223,7 +223,7 @@ void Ogg::FLAC::File::scan()
705     return;
706
707   int ipacket = 0;
708-  long overhead = 0;
709+  offset_t overhead = 0;
710
711   ByteVector metadataHeader = packet(ipacket);
712   if(metadataHeader.isEmpty())
713diff --git a/taglib/ogg/flac/oggflacfile.h b/taglib/ogg/flac/oggflacfile.h
714index b2686e45..0e5e1ac4 100644
715--- a/taglib/ogg/flac/oggflacfile.h
716+++ b/taglib/ogg/flac/oggflacfile.h
717@@ -134,7 +134,7 @@ namespace TagLib {
718        * Returns the length of the audio-stream, used by FLAC::Properties for
719        * calculating the bitrate.
720        */
721-      long streamLength();
722+      offset_t streamLength();
723
724       /*!
725        * Returns whether or not the file on disk actually has a XiphComment.
726diff --git a/taglib/ogg/oggfile.cpp b/taglib/ogg/oggfile.cpp
727index c36e4d46..aa284a3b 100644
728--- a/taglib/ogg/oggfile.cpp
729+++ b/taglib/ogg/oggfile.cpp
730@@ -130,7 +130,7 @@ void Ogg::File::setPacket(unsigned int i, const ByteVector &p)
731 const Ogg::PageHeader *Ogg::File::firstPageHeader()
732 {
733   if(!d->firstPageHeader) {
734-    const long firstPageHeaderOffset = find("OggS");
735+    const offset_t firstPageHeaderOffset = find("OggS");
736     if(firstPageHeaderOffset < 0)
737       return 0;
738
739@@ -143,7 +143,7 @@ const Ogg::PageHeader *Ogg::File::firstPageHeader()
740 const Ogg::PageHeader *Ogg::File::lastPageHeader()
741 {
742   if(!d->lastPageHeader) {
743-    const long lastPageHeaderOffset = rfind("OggS");
744+    const offset_t lastPageHeaderOffset = rfind("OggS");
745     if(lastPageHeaderOffset < 0)
746       return 0;
747
748@@ -193,7 +193,7 @@ bool Ogg::File::readPages(unsigned int i)
749 {
750   while(true) {
751     unsigned int packetIndex;
752-    long offset;
753+    offset_t offset;
754
755     if(d->pages.isEmpty()) {
756       packetIndex = 0;
757@@ -276,8 +276,8 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
758   for(it = pages.begin(); it != pages.end(); ++it)
759     data.append((*it)->render());
760
761-  const unsigned long originalOffset = firstPage->fileOffset();
762-  const unsigned long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
763+  const offset_t originalOffset = firstPage->fileOffset();
764+  const offset_t originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
765
766   insert(data, originalOffset, originalLength);
767
768diff --git a/taglib/ogg/oggpage.cpp b/taglib/ogg/oggpage.cpp
769index 414d3d53..12186062 100644
770--- a/taglib/ogg/oggpage.cpp
771+++ b/taglib/ogg/oggpage.cpp
772@@ -37,14 +37,14 @@ using namespace TagLib;
773 class Ogg::Page::PagePrivate
774 {
775 public:
776-  PagePrivate(File *f = 0, long pageOffset = -1) :
777+  PagePrivate(File *f = 0, offset_t pageOffset = -1) :
778     file(f),
779     fileOffset(pageOffset),
780     header(f, pageOffset),
781     firstPacketIndex(-1) {}
782
783   File *file;
784-  long fileOffset;
785+  offset_t fileOffset;
786   PageHeader header;
787   int firstPacketIndex;
788   ByteVectorList packets;
789@@ -54,7 +54,7 @@ public:
790 // public members
791 ////////////////////////////////////////////////////////////////////////////////
792
793-Ogg::Page::Page(Ogg::File *file, long pageOffset) :
794+Ogg::Page::Page(Ogg::File *file, offset_t pageOffset) :
795   d(new PagePrivate(file, pageOffset))
796 {
797 }
798@@ -64,7 +64,7 @@ Ogg::Page::~Page()
799   delete d;
800 }
801
802-long Ogg::Page::fileOffset() const
803+offset_t Ogg::Page::fileOffset() const
804 {
805   return d->fileOffset;
806 }
807diff --git a/taglib/ogg/oggpage.h b/taglib/ogg/oggpage.h
808index af3fe2c9..3df200e8 100644
809--- a/taglib/ogg/oggpage.h
810+++ b/taglib/ogg/oggpage.h
811@@ -55,14 +55,14 @@ namespace TagLib {
812       /*!
813        * Read an Ogg page from the \a file at the position \a pageOffset.
814        */
815-      Page(File *file, long pageOffset);
816+      Page(File *file, offset_t pageOffset);
817
818       virtual ~Page();
819
820       /*!
821        * Returns the page's position within the file (in bytes).
822        */
823-      long fileOffset() const;
824+      offset_t fileOffset() const;
825
826       /*!
827        * Returns a pointer to the header for this page.  This pointer will become
828diff --git a/taglib/ogg/oggpageheader.cpp b/taglib/ogg/oggpageheader.cpp
829index b867567c..cc645eaf 100644
830--- a/taglib/ogg/oggpageheader.cpp
831+++ b/taglib/ogg/oggpageheader.cpp
832@@ -66,7 +66,7 @@ public:
833 // public members
834 ////////////////////////////////////////////////////////////////////////////////
835
836-Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) :
837+Ogg::PageHeader::PageHeader(Ogg::File *file, offset_t pageOffset) :
838   d(new PageHeaderPrivate())
839 {
840   if(file && pageOffset >= 0)
841@@ -225,7 +225,7 @@ ByteVector Ogg::PageHeader::render() const
842 // private members
843 ////////////////////////////////////////////////////////////////////////////////
844
845-void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
846+void Ogg::PageHeader::read(Ogg::File *file, offset_t pageOffset)
847 {
848   file->seek(pageOffset);
849
850diff --git a/taglib/ogg/oggpageheader.h b/taglib/ogg/oggpageheader.h
851index 571155fc..d6c714c1 100644
852--- a/taglib/ogg/oggpageheader.h
853+++ b/taglib/ogg/oggpageheader.h
854@@ -52,7 +52,7 @@ namespace TagLib {
855        * create a page with no (and as such, invalid) data that must be set
856        * later.
857        */
858-      PageHeader(File *file = 0, long pageOffset = -1);
859+      PageHeader(File *file = 0, offset_t pageOffset = -1);
860
861       /*!
862        * Deletes this instance of the PageHeader.
863@@ -219,7 +219,7 @@ namespace TagLib {
864       PageHeader(const PageHeader &);
865       PageHeader &operator=(const PageHeader &);
866
867-      void read(Ogg::File *file, long pageOffset);
868+      void read(Ogg::File *file, offset_t pageOffset);
869       ByteVector lacingValues() const;
870
871       class PageHeaderPrivate;
872diff --git a/taglib/ogg/opus/opusproperties.cpp b/taglib/ogg/opus/opusproperties.cpp
873index b60cc01d..e19ab64d 100644
874--- a/taglib/ogg/opus/opusproperties.cpp
875+++ b/taglib/ogg/opus/opusproperties.cpp
876@@ -163,7 +163,7 @@ void Opus::Properties::read(File *file)
877
878       if(frameCount > 0) {
879         const double length = frameCount * 1000.0 / 48000.0;
880-        long fileLengthWithoutOverhead = file->length();
881+        offset_t fileLengthWithoutOverhead = file->length();
882         // Ignore the two mandatory header packets, see "3. Packet Organization"
883         // in https://tools.ietf.org/html/rfc7845.html
884         for (unsigned int i = 0; i < 2; ++i) {
885diff --git a/taglib/ogg/speex/speexproperties.cpp b/taglib/ogg/speex/speexproperties.cpp
886index b7a11cc6..fae184a0 100644
887--- a/taglib/ogg/speex/speexproperties.cpp
888+++ b/taglib/ogg/speex/speexproperties.cpp
889@@ -182,7 +182,7 @@ void Speex::Properties::read(File *file)
890
891       if(frameCount > 0) {
892         const double length = frameCount * 1000.0 / d->sampleRate;
893-        long fileLengthWithoutOverhead = file->length();
894+        offset_t fileLengthWithoutOverhead = file->length();
895         // Ignore the two header packets, see "Ogg file format" in
896         // https://www.speex.org/docs/manual/speex-manual/node8.html
897         for (unsigned int i = 0; i < 2; ++i) {
898diff --git a/taglib/ogg/vorbis/vorbisproperties.cpp b/taglib/ogg/vorbis/vorbisproperties.cpp
899index 4000c254..6f6c8907 100644
900--- a/taglib/ogg/vorbis/vorbisproperties.cpp
901+++ b/taglib/ogg/vorbis/vorbisproperties.cpp
902@@ -186,7 +186,7 @@ void Vorbis::Properties::read(File *file)
903
904       if(frameCount > 0) {
905         const double length = frameCount * 1000.0 / d->sampleRate;
906-        long fileLengthWithoutOverhead = file->length();
907+        offset_t fileLengthWithoutOverhead = file->length();
908         // Ignore the three initial header packets, see "1.3.1. Decode Setup" in
909         // https://xiph.org/vorbis/doc/Vorbis_I_spec.html
910         for (unsigned int i = 0; i < 3; ++i) {
911diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp
912index 005551f4..87ce7240 100644
913--- a/taglib/riff/rifffile.cpp
914+++ b/taglib/riff/rifffile.cpp
915@@ -38,7 +38,7 @@ using namespace TagLib;
916 struct Chunk
917 {
918   ByteVector   name;
919-  unsigned int offset;
920+  offset_t offset;
921   unsigned int size;
922   unsigned int padding;
923 };
924@@ -54,7 +54,7 @@ public:
925   const Endianness endianness;
926
927   unsigned int size;
928-  long sizeOffset;
929+  offset_t sizeOffset;
930
931   std::vector<Chunk> chunks;
932 };
933@@ -108,7 +108,7 @@ unsigned int RIFF::File::chunkDataSize(unsigned int i) const
934   return d->chunks[i].size;
935 }
936
937-unsigned int RIFF::File::chunkOffset(unsigned int i) const
938+offset_t RIFF::File::chunkOffset(unsigned int i) const
939 {
940   if(i >= d->chunks.size()) {
941     debug("RIFF::File::chunkOffset() - Index out of range. Returning 0.");
942@@ -212,7 +212,7 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
943
944   Chunk &last = d->chunks.back();
945
946-  long offset = last.offset + last.size + last.padding;
947+  offset_t offset = last.offset + last.size + last.padding;
948   if(offset & 1) {
949     if(last.padding == 1) {
950       last.padding = 0; // This should not happen unless the file is corrupted.
951@@ -283,7 +283,7 @@ void RIFF::File::read()
952 {
953   const bool bigEndian = (d->endianness == BigEndian);
954
955-  long offset = tell();
956+  offset_t offset = tell();
957
958   offset += 4;
959   d->sizeOffset = offset;
960@@ -345,7 +345,7 @@ void RIFF::File::read()
961 }
962
963 void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
964-                            unsigned long offset, unsigned long replace)
965+                            offset_t offset, unsigned long replace)
966 {
967   ByteVector combined;
968
969diff --git a/taglib/riff/rifffile.h b/taglib/riff/rifffile.h
970index 5c606b4a..cf821baf 100644
971--- a/taglib/riff/rifffile.h
972+++ b/taglib/riff/rifffile.h
973@@ -71,7 +71,7 @@ namespace TagLib {
974       /*!
975        * \return The offset within the file for the selected chunk number.
976        */
977-      unsigned int chunkOffset(unsigned int i) const;
978+      offset_t chunkOffset(unsigned int i) const;
979
980       /*!
981        * \return The size of the chunk data.
982@@ -145,7 +145,7 @@ namespace TagLib {
983
984       void read();
985       void writeChunk(const ByteVector &name, const ByteVector &data,
986-                      unsigned long offset, unsigned long replace = 0);
987+                      offset_t offset, unsigned long replace = 0);
988
989       /*!
990        * Update the global RIFF size based on the current internal structure.
991diff --git a/taglib/tagutils.cpp b/taglib/tagutils.cpp
992index d6d92406..82dc2fa2 100644
993--- a/taglib/tagutils.cpp
994+++ b/taglib/tagutils.cpp
995@@ -33,13 +33,13 @@
996
997 using namespace TagLib;
998
999-long Utils::findID3v1(File *file)
1000+offset_t Utils::findID3v1(File *file)
1001 {
1002   if(!file->isValid())
1003     return -1;
1004
1005   file->seek(-128, File::End);
1006-  const long p = file->tell();
1007+  const offset_t p = file->tell();
1008
1009   if(file->readBlock(3) == ID3v1::Tag::fileIdentifier())
1010     return p;
1011@@ -47,7 +47,7 @@ long Utils::findID3v1(File *file)
1012   return -1;
1013 }
1014
1015-long Utils::findID3v2(File *file)
1016+offset_t Utils::findID3v2(File *file)
1017 {
1018   if(!file->isValid())
1019     return -1;
1020@@ -60,7 +60,7 @@ long Utils::findID3v2(File *file)
1021   return -1;
1022 }
1023
1024-long Utils::findAPE(File *file, long id3v1Location)
1025+offset_t Utils::findAPE(File *file, offset_t id3v1Location)
1026 {
1027   if(!file->isValid())
1028     return -1;
1029@@ -70,7 +70,7 @@ long Utils::findAPE(File *file, long id3v1Location)
1030   else
1031     file->seek(-32, File::End);
1032
1033-  const long p = file->tell();
1034+  const offset_t p = file->tell();
1035
1036   if(file->readBlock(8) == APE::Tag::fileIdentifier())
1037     return p;
1038@@ -79,13 +79,13 @@ long Utils::findAPE(File *file, long id3v1Location)
1039 }
1040
1041 ByteVector TagLib::Utils::readHeader(IOStream *stream, unsigned int length,
1042-                                     bool skipID3v2, long *headerOffset)
1043+                                     bool skipID3v2, offset_t *headerOffset)
1044 {
1045   if(!stream || !stream->isOpen())
1046     return ByteVector();
1047
1048-  const long originalPosition = stream->tell();
1049-  long bufferOffset = 0;
1050+  const offset_t originalPosition = stream->tell();
1051+  offset_t bufferOffset = 0;
1052
1053   if(skipID3v2) {
1054     stream->seek(0);
1055diff --git a/taglib/tagutils.h b/taglib/tagutils.h
1056index 4488a32b..47d77246 100644
1057--- a/taglib/tagutils.h
1058+++ b/taglib/tagutils.h
1059@@ -39,14 +39,14 @@ namespace TagLib {
1060
1061   namespace Utils {
1062
1063-    long findID3v1(File *file);
1064+    offset_t findID3v1(File *file);
1065
1066-    long findID3v2(File *file);
1067+    offset_t findID3v2(File *file);
1068
1069-    long findAPE(File *file, long id3v1Location);
1070+    offset_t findAPE(File *file, offset_t id3v1Location);
1071
1072     ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2,
1073-                          long *headerOffset = 0);
1074+                          offset_t *headerOffset = 0);
1075   }
1076 }
1077
1078diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h
1079index ffce61f7..c7125d3e 100644
1080--- a/taglib/toolkit/taglib.h
1081+++ b/taglib/toolkit/taglib.h
1082@@ -54,6 +54,11 @@
1083 #define TAGLIB_DEPRECATED
1084 #endif
1085
1086+#define TAGLIB_WITH_OFFSET_TYPE
1087+#ifndef _WIN32
1088+#include <sys/types.h>
1089+#endif
1090+
1091 #include <string>
1092
1093 //! A namespace for all TagLib related classes and functions
1094@@ -79,6 +84,14 @@ namespace TagLib {
1095   typedef unsigned long      ulong;
1096   typedef unsigned long long ulonglong;
1097
1098+  // Offset or length type for I/O streams.
1099+  // In Win32, always 64bit. Otherwise, equivalent to off_t.
1100+#ifdef _WIN32
1101+  typedef long long offset_t;
1102+#else
1103+  typedef off_t     offset_t;
1104+#endif
1105+
1106   /*!
1107    * Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3)
1108    * so I'm providing something here that should be constant.
1109diff --git a/taglib/toolkit/tbytevectorstream.cpp b/taglib/toolkit/tbytevectorstream.cpp
1110index 333f528c..978fb23f 100644
1111--- a/taglib/toolkit/tbytevectorstream.cpp
1112+++ b/taglib/toolkit/tbytevectorstream.cpp
1113@@ -40,7 +40,7 @@ public:
1114   ByteVectorStreamPrivate(const ByteVector &data);
1115
1116   ByteVector data;
1117-  long position;
1118+  offset_t position;
1119 };
1120
1121 ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) :
1122@@ -88,7 +88,7 @@ void ByteVectorStream::writeBlock(const ByteVector &data)
1123   d->position += size;
1124 }
1125
1126-void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
1127+void ByteVectorStream::insert(const ByteVector &data, offset_t start, unsigned long replace)
1128 {
1129   long sizeDiff = data.size() - replace;
1130   if(sizeDiff < 0) {
1131@@ -96,19 +96,19 @@ void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsig
1132   }
1133   else if(sizeDiff > 0) {
1134     truncate(length() + sizeDiff);
1135-    unsigned long readPosition  = start + replace;
1136-    unsigned long writePosition = start + data.size();
1137+    offset_t readPosition  = start + replace;
1138+    offset_t writePosition = start + data.size();
1139     memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition);
1140   }
1141   seek(start);
1142   writeBlock(data);
1143 }
1144
1145-void ByteVectorStream::removeBlock(unsigned long start, unsigned long length)
1146+void ByteVectorStream::removeBlock(offset_t start, unsigned long length)
1147 {
1148-  unsigned long readPosition = start + length;
1149-  unsigned long writePosition = start;
1150-  if(readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
1151+  offset_t readPosition = start + length;
1152+  offset_t writePosition = start;
1153+  if(readPosition < ByteVectorStream::length()) {
1154     unsigned long bytesToMove = ByteVectorStream::length() - readPosition;
1155     memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove);
1156     writePosition += bytesToMove;
1157@@ -127,7 +127,7 @@ bool ByteVectorStream::isOpen() const
1158   return true;
1159 }
1160
1161-void ByteVectorStream::seek(long offset, Position p)
1162+void ByteVectorStream::seek(offset_t offset, Position p)
1163 {
1164   switch(p) {
1165   case Beginning:
1166@@ -146,17 +146,17 @@ void ByteVectorStream::clear()
1167 {
1168 }
1169
1170-long ByteVectorStream::tell() const
1171+offset_t ByteVectorStream::tell() const
1172 {
1173   return d->position;
1174 }
1175
1176-long ByteVectorStream::length()
1177+offset_t ByteVectorStream::length()
1178 {
1179   return d->data.size();
1180 }
1181
1182-void ByteVectorStream::truncate(long length)
1183+void ByteVectorStream::truncate(offset_t length)
1184 {
1185   d->data.resize(length);
1186 }
1187diff --git a/taglib/toolkit/tbytevectorstream.h b/taglib/toolkit/tbytevectorstream.h
1188index 84327c46..78ebfd4a 100644
1189--- a/taglib/toolkit/tbytevectorstream.h
1190+++ b/taglib/toolkit/tbytevectorstream.h
1191@@ -81,7 +81,7 @@ namespace TagLib {
1192      * \note This method is slow since it requires rewriting all of the file
1193      * after the insertion point.
1194      */
1195-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
1196+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
1197
1198     /*!
1199      * Removes a block of the file starting a \a start and continuing for
1200@@ -90,7 +90,7 @@ namespace TagLib {
1201      * \note This method is slow since it involves rewriting all of the file
1202      * after the removed portion.
1203      */
1204-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
1205+    void removeBlock(offset_t start = 0, unsigned long length = 0);
1206
1207     /*!
1208      * Returns true if the file is read only (or if the file can not be opened).
1209@@ -109,7 +109,7 @@ namespace TagLib {
1210      *
1211      * \see Position
1212      */
1213-    void seek(long offset, Position p = Beginning);
1214+    void seek(offset_t offset, Position p = Beginning);
1215
1216     /*!
1217      * Reset the end-of-file and error flags on the file.
1218@@ -119,17 +119,17 @@ namespace TagLib {
1219     /*!
1220      * Returns the current offset within the file.
1221      */
1222-    long tell() const;
1223+    offset_t tell() const;
1224
1225     /*!
1226      * Returns the length of the file.
1227      */
1228-    long length();
1229+    offset_t length();
1230
1231     /*!
1232      * Truncates the file to a \a length.
1233      */
1234-    void truncate(long length);
1235+    void truncate(offset_t length);
1236
1237     ByteVector *data();
1238
1239diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp
1240index aff1684d..3985885c 100644
1241--- a/taglib/toolkit/tfile.cpp
1242+++ b/taglib/toolkit/tfile.cpp
1243@@ -233,14 +233,14 @@ void File::writeBlock(const ByteVector &data)
1244   d->stream->writeBlock(data);
1245 }
1246
1247-long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before)
1248+offset_t File::find(const ByteVector &pattern, offset_t fromOffset, const ByteVector &before)
1249 {
1250   if(!d->stream || pattern.size() > bufferSize())
1251       return -1;
1252
1253   // The position in the file that the current buffer starts at.
1254
1255-  long bufferOffset = fromOffset;
1256+  offset_t bufferOffset = fromOffset;
1257   ByteVector buffer;
1258
1259   // These variables are used to keep track of a partial match that happens at
1260@@ -252,7 +252,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
1261   // Save the location of the current read pointer.  We will restore the
1262   // position using seek() before all returns.
1263
1264-  long originalPosition = tell();
1265+  offset_t originalPosition = tell();
1266
1267   // Start the search at the offset.
1268
1269@@ -329,7 +329,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
1270 }
1271
1272
1273-long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before)
1274+offset_t File::rfind(const ByteVector &pattern, offset_t fromOffset, const ByteVector &before)
1275 {
1276   if(!d->stream || pattern.size() > bufferSize())
1277       return -1;
1278@@ -349,7 +349,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
1279   // Save the location of the current read pointer.  We will restore the
1280   // position using seek() before all returns.
1281
1282-  long originalPosition = tell();
1283+  offset_t originalPosition = tell();
1284
1285   // Start the search at the offset.
1286
1287@@ -357,7 +357,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
1288     fromOffset = length();
1289
1290   long bufferLength = bufferSize();
1291-  long bufferOffset = fromOffset + pattern.size();
1292+  offset_t bufferOffset = fromOffset + pattern.size();
1293
1294   // See the notes in find() for an explanation of this algorithm.
1295
1296@@ -403,12 +403,12 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
1297   return -1;
1298 }
1299
1300-void File::insert(const ByteVector &data, unsigned long start, unsigned long replace)
1301+void File::insert(const ByteVector &data, offset_t start, unsigned long replace)
1302 {
1303   d->stream->insert(data, start, replace);
1304 }
1305
1306-void File::removeBlock(unsigned long start, unsigned long length)
1307+void File::removeBlock(offset_t start, unsigned long length)
1308 {
1309   d->stream->removeBlock(start, length);
1310 }
1311@@ -428,12 +428,12 @@ bool File::isValid() const
1312   return isOpen() && d->valid;
1313 }
1314
1315-void File::seek(long offset, Position p)
1316+void File::seek(offset_t offset, Position p)
1317 {
1318   d->stream->seek(offset, IOStream::Position(p));
1319 }
1320
1321-void File::truncate(long length)
1322+void File::truncate(offset_t length)
1323 {
1324   d->stream->truncate(length);
1325 }
1326@@ -443,12 +443,12 @@ void File::clear()
1327   d->stream->clear();
1328 }
1329
1330-long File::tell() const
1331+offset_t File::tell() const
1332 {
1333   return d->stream->tell();
1334 }
1335
1336-long File::length()
1337+offset_t File::length()
1338 {
1339   return d->stream->length();
1340 }
1341diff --git a/taglib/toolkit/tfile.h b/taglib/toolkit/tfile.h
1342index bdc4f124..4c87fb36 100644
1343--- a/taglib/toolkit/tfile.h
1344+++ b/taglib/toolkit/tfile.h
1345@@ -180,8 +180,8 @@ namespace TagLib {
1346      * \note This has the practical limitation that \a pattern can not be longer
1347      * than the buffer size used by readBlock().  Currently this is 1024 bytes.
1348      */
1349-    long find(const ByteVector &pattern,
1350-              long fromOffset = 0,
1351+    offset_t find(const ByteVector &pattern,
1352+              offset_t fromOffset = 0,
1353               const ByteVector &before = ByteVector());
1354
1355     /*!
1356@@ -196,8 +196,8 @@ namespace TagLib {
1357      * \note This has the practical limitation that \a pattern can not be longer
1358      * than the buffer size used by readBlock().  Currently this is 1024 bytes.
1359      */
1360-    long rfind(const ByteVector &pattern,
1361-               long fromOffset = 0,
1362+    offset_t rfind(const ByteVector &pattern,
1363+               offset_t fromOffset = 0,
1364                const ByteVector &before = ByteVector());
1365
1366     /*!
1367@@ -207,7 +207,7 @@ namespace TagLib {
1368      * \note This method is slow since it requires rewriting all of the file
1369      * after the insertion point.
1370      */
1371-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
1372+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
1373
1374     /*!
1375      * Removes a block of the file starting a \a start and continuing for
1376@@ -216,7 +216,7 @@ namespace TagLib {
1377      * \note This method is slow since it involves rewriting all of the file
1378      * after the removed portion.
1379      */
1380-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
1381+    void removeBlock(offset_t start = 0, unsigned long length = 0);
1382
1383     /*!
1384      * Returns true if the file is read only (or if the file can not be opened).
1385@@ -240,7 +240,7 @@ namespace TagLib {
1386      *
1387      * \see Position
1388      */
1389-    void seek(long offset, Position p = Beginning);
1390+    void seek(offset_t offset, Position p = Beginning);
1391
1392     /*!
1393      * Reset the end-of-file and error flags on the file.
1394@@ -250,12 +250,12 @@ namespace TagLib {
1395     /*!
1396      * Returns the current offset within the file.
1397      */
1398-    long tell() const;
1399+    offset_t tell() const;
1400
1401     /*!
1402      * Returns the length of the file.
1403      */
1404-    long length();
1405+    offset_t length();
1406
1407     /*!
1408      * Returns true if \a file can be opened for reading.  If the file does not
1409@@ -303,7 +303,7 @@ namespace TagLib {
1410     /*!
1411      * Truncates the file to a \a length.
1412      */
1413-    void truncate(long length);
1414+    void truncate(offset_t length);
1415
1416     /*!
1417      * Returns the buffer size that is used for internal buffering.
1418diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp
1419index 0ea3be5b..81cadace 100644
1420--- a/taglib/toolkit/tfilestream.cpp
1421+++ b/taglib/toolkit/tfilestream.cpp
1422@@ -233,7 +233,7 @@ void FileStream::writeBlock(const ByteVector &data)
1423   writeFile(d->file, data);
1424 }
1425
1426-void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
1427+void FileStream::insert(const ByteVector &data, offset_t start, unsigned long replace)
1428 {
1429   if(!isOpen()) {
1430     debug("FileStream::insert() -- invalid file.");
1431@@ -267,15 +267,15 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
1432   // the *difference* in the tag sizes.  We want to avoid overwriting parts
1433   // that aren't yet in memory, so this is necessary.
1434
1435-  unsigned long bufferLength = bufferSize();
1436+  size_t bufferLength = bufferSize();
1437
1438   while(data.size() - replace > bufferLength)
1439     bufferLength += bufferSize();
1440
1441   // Set where to start the reading and writing.
1442
1443-  long readPosition = start + replace;
1444-  long writePosition = start;
1445+  offset_t readPosition = start + replace;
1446+  offset_t writePosition = start;
1447
1448   ByteVector buffer = data;
1449   ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
1450@@ -314,7 +314,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
1451   }
1452 }
1453
1454-void FileStream::removeBlock(unsigned long start, unsigned long length)
1455+void FileStream::removeBlock(offset_t start, unsigned long length)
1456 {
1457   if(!isOpen()) {
1458     debug("FileStream::removeBlock() -- invalid file.");
1459@@ -323,8 +323,8 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
1460
1461   unsigned long bufferLength = bufferSize();
1462
1463-  long readPosition = start + length;
1464-  long writePosition = start;
1465+  offset_t readPosition = start + length;
1466+  offset_t writePosition = start;
1467
1468   ByteVector buffer(static_cast<unsigned int>(bufferLength));
1469
1470@@ -360,7 +360,7 @@ bool FileStream::isOpen() const
1471   return (d->file != InvalidFileHandle);
1472 }
1473
1474-void FileStream::seek(long offset, Position p)
1475+void FileStream::seek(offset_t offset, Position p)
1476 {
1477   if(!isOpen()) {
1478     debug("FileStream::seek() -- invalid file.");
1479@@ -417,16 +417,15 @@ void FileStream::clear()
1480 #endif
1481 }
1482
1483-long FileStream::tell() const
1484+offset_t FileStream::tell() const
1485 {
1486 #ifdef _WIN32
1487
1488   const LARGE_INTEGER zero = {};
1489   LARGE_INTEGER position;
1490
1491-  if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
1492-     position.QuadPart <= LONG_MAX) {
1493-    return static_cast<long>(position.QuadPart);
1494+  if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT)) {
1495+    return position.QuadPart;
1496   }
1497   else {
1498     debug("FileStream::tell() -- Failed to get the file pointer.");
1499@@ -440,7 +439,7 @@ long FileStream::tell() const
1500 #endif
1501 }
1502
1503-long FileStream::length()
1504+offset_t FileStream::length()
1505 {
1506   if(!isOpen()) {
1507     debug("FileStream::length() -- invalid file.");
1508@@ -461,10 +460,10 @@ long FileStream::length()
1509
1510 #else
1511
1512-  const long curpos = tell();
1513+  const offset_t curpos = tell();
1514
1515   seek(0, End);
1516-  const long endpos = tell();
1517+  const offset_t endpos = tell();
1518
1519   seek(curpos, Beginning);
1520
1521@@ -477,11 +476,11 @@ long FileStream::length()
1522 // protected members
1523 ////////////////////////////////////////////////////////////////////////////////
1524
1525-void FileStream::truncate(long length)
1526+void FileStream::truncate(offset_t length)
1527 {
1528 #ifdef _WIN32
1529
1530-  const long currentPos = tell();
1531+  const offset_t currentPos = tell();
1532
1533   seek(length);
1534
1535diff --git a/taglib/toolkit/tfilestream.h b/taglib/toolkit/tfilestream.h
1536index aa4d71b3..4f47b26e 100644
1537--- a/taglib/toolkit/tfilestream.h
1538+++ b/taglib/toolkit/tfilestream.h
1539@@ -92,7 +92,7 @@ namespace TagLib {
1540      * \note This method is slow since it requires rewriting all of the file
1541      * after the insertion point.
1542      */
1543-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
1544+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
1545
1546     /*!
1547      * Removes a block of the file starting a \a start and continuing for
1548@@ -101,7 +101,7 @@ namespace TagLib {
1549      * \note This method is slow since it involves rewriting all of the file
1550      * after the removed portion.
1551      */
1552-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
1553+    void removeBlock(offset_t start = 0, unsigned long length = 0);
1554
1555     /*!
1556      * Returns true if the file is read only (or if the file can not be opened).
1557@@ -120,7 +120,7 @@ namespace TagLib {
1558      *
1559      * \see Position
1560      */
1561-    void seek(long offset, Position p = Beginning);
1562+    void seek(offset_t offset, Position p = Beginning);
1563
1564     /*!
1565      * Reset the end-of-file and error flags on the file.
1566@@ -130,17 +130,17 @@ namespace TagLib {
1567     /*!
1568      * Returns the current offset within the file.
1569      */
1570-    long tell() const;
1571+    offset_t tell() const;
1572
1573     /*!
1574      * Returns the length of the file.
1575      */
1576-    long length();
1577+    offset_t length();
1578
1579     /*!
1580      * Truncates the file to a \a length.
1581      */
1582-    void truncate(long length);
1583+    void truncate(offset_t length);
1584
1585   protected:
1586
1587diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h
1588index 11053164..25417fce 100644
1589--- a/taglib/toolkit/tiostream.h
1590+++ b/taglib/toolkit/tiostream.h
1591@@ -110,7 +110,7 @@ namespace TagLib {
1592      * after the insertion point.
1593      */
1594     virtual void insert(const ByteVector &data,
1595-                        unsigned long start = 0, unsigned long replace = 0) = 0;
1596+                        offset_t start = 0, unsigned long replace = 0) = 0;
1597
1598     /*!
1599      * Removes a block of the file starting a \a start and continuing for
1600@@ -119,7 +119,7 @@ namespace TagLib {
1601      * \note This method is slow since it involves rewriting all of the file
1602      * after the removed portion.
1603      */
1604-    virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0;
1605+    virtual void removeBlock(offset_t start = 0, unsigned long length = 0) = 0;
1606
1607     /*!
1608      * Returns true if the file is read only (or if the file can not be opened).
1609@@ -138,7 +138,7 @@ namespace TagLib {
1610      *
1611      * \see Position
1612      */
1613-    virtual void seek(long offset, Position p = Beginning) = 0;
1614+    virtual void seek(offset_t offset, Position p = Beginning) = 0;
1615
1616     /*!
1617      * Reset the end-of-stream and error flags on the stream.
1618@@ -148,17 +148,17 @@ namespace TagLib {
1619     /*!
1620      * Returns the current offset within the stream.
1621      */
1622-    virtual long tell() const = 0;
1623+    virtual offset_t tell() const = 0;
1624
1625     /*!
1626      * Returns the length of the stream.
1627      */
1628-    virtual long length() = 0;
1629+    virtual offset_t length() = 0;
1630
1631     /*!
1632      * Truncates the stream to a \a length.
1633      */
1634-    virtual void truncate(long length) = 0;
1635+    virtual void truncate(offset_t length) = 0;
1636
1637   private:
1638     IOStream(const IOStream &);
1639diff --git a/taglib/trueaudio/trueaudiofile.cpp b/taglib/trueaudio/trueaudiofile.cpp
1640index e4de436e..6afd8a5d 100644
1641--- a/taglib/trueaudio/trueaudiofile.cpp
1642+++ b/taglib/trueaudio/trueaudiofile.cpp
1643@@ -63,10 +63,10 @@ public:
1644   }
1645
1646   const ID3v2::FrameFactory *ID3v2FrameFactory;
1647-  long ID3v2Location;
1648+  offset_t ID3v2Location;
1649   long ID3v2OriginalSize;
1650
1651-  long ID3v1Location;
1652+  offset_t ID3v1Location;
1653
1654   TagUnion tag;
1655
1656@@ -290,7 +290,7 @@ void TrueAudio::File::read(bool readProperties)
1657
1658   if(readProperties) {
1659
1660-    long streamLength;
1661+    offset_t streamLength;
1662
1663     if(d->ID3v1Location >= 0)
1664       streamLength = d->ID3v1Location;
1665diff --git a/taglib/trueaudio/trueaudioproperties.cpp b/taglib/trueaudio/trueaudioproperties.cpp
1666index 0aab2419..3a403848 100644
1667--- a/taglib/trueaudio/trueaudioproperties.cpp
1668+++ b/taglib/trueaudio/trueaudioproperties.cpp
1669@@ -61,7 +61,7 @@ public:
1670 // public members
1671 ////////////////////////////////////////////////////////////////////////////////
1672
1673-TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
1674+TrueAudio::Properties::Properties(const ByteVector &data, offset_t streamLength, ReadStyle style) :
1675   AudioProperties(style),
1676   d(new PropertiesPrivate())
1677 {
1678@@ -122,7 +122,7 @@ int TrueAudio::Properties::ttaVersion() const
1679 // private members
1680 ////////////////////////////////////////////////////////////////////////////////
1681
1682-void TrueAudio::Properties::read(const ByteVector &data, long streamLength)
1683+void TrueAudio::Properties::read(const ByteVector &data, offset_t streamLength)
1684 {
1685   if(data.size() < 4) {
1686     debug("TrueAudio::Properties::read() -- data is too short.");
1687diff --git a/taglib/trueaudio/trueaudioproperties.h b/taglib/trueaudio/trueaudioproperties.h
1688index d25c7a77..fbf1ee75 100644
1689--- a/taglib/trueaudio/trueaudioproperties.h
1690+++ b/taglib/trueaudio/trueaudioproperties.h
1691@@ -54,7 +54,7 @@ namespace TagLib {
1692        * Create an instance of TrueAudio::Properties with the data read from the
1693        * ByteVector \a data.
1694        */
1695-      Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
1696+      Properties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
1697
1698       /*!
1699        * Destroys this TrueAudio::Properties instance.
1700@@ -122,7 +122,7 @@ namespace TagLib {
1701       Properties(const Properties &);
1702       Properties &operator=(const Properties &);
1703
1704-      void read(const ByteVector &data, long streamLength);
1705+      void read(const ByteVector &data, offset_t streamLength);
1706
1707       class PropertiesPrivate;
1708       PropertiesPrivate *d;
1709diff --git a/taglib/wavpack/wavpackfile.cpp b/taglib/wavpack/wavpackfile.cpp
1710index 56b99393..af63c491 100644
1711--- a/taglib/wavpack/wavpackfile.cpp
1712+++ b/taglib/wavpack/wavpackfile.cpp
1713@@ -61,10 +61,10 @@ public:
1714     delete properties;
1715   }
1716
1717-  long APELocation;
1718+  offset_t APELocation;
1719   long APESize;
1720
1721-  long ID3v1Location;
1722+  offset_t ID3v1Location;
1723
1724   TagUnion tag;
1725
1726@@ -270,7 +270,7 @@ void WavPack::File::read(bool readProperties)
1727
1728   if(readProperties) {
1729
1730-    long streamLength;
1731+    offset_t streamLength;
1732
1733     if(d->APELocation >= 0)
1734       streamLength = d->APELocation;
1735diff --git a/taglib/wavpack/wavpackproperties.cpp b/taglib/wavpack/wavpackproperties.cpp
1736index d5808be5..5cc061e2 100644
1737--- a/taglib/wavpack/wavpackproperties.cpp
1738+++ b/taglib/wavpack/wavpackproperties.cpp
1739@@ -66,14 +66,14 @@ public:
1740 // public members
1741 ////////////////////////////////////////////////////////////////////////////////
1742
1743-WavPack::Properties::Properties(const ByteVector &, long, ReadStyle style) :
1744+WavPack::Properties::Properties(const ByteVector &, offset_t, ReadStyle style) :
1745   AudioProperties(style),
1746   d(new PropertiesPrivate())
1747 {
1748   debug("WavPack::Properties::Properties() -- This constructor is no longer used.");
1749 }
1750
1751-WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) :
1752+WavPack::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
1753   AudioProperties(style),
1754   d(new PropertiesPrivate())
1755 {
1756@@ -257,9 +257,9 @@ namespace
1757
1758 }
1759
1760-void WavPack::Properties::read(File *file, long streamLength)
1761+void WavPack::Properties::read(File *file, offset_t streamLength)
1762 {
1763-  long offset = 0;
1764+  offset_t offset = 0;
1765
1766   while(true) {
1767     file->seek(offset);
1768@@ -339,9 +339,9 @@ void WavPack::Properties::read(File *file, long streamLength)
1769   }
1770 }
1771
1772-unsigned int WavPack::Properties::seekFinalIndex(File *file, long streamLength)
1773+unsigned int WavPack::Properties::seekFinalIndex(File *file, offset_t streamLength)
1774 {
1775-  long offset = streamLength;
1776+  offset_t offset = streamLength;
1777
1778   while (offset >= 32) {
1779     offset = file->rfind("wvpk", offset - 4);
1780diff --git a/taglib/wavpack/wavpackproperties.h b/taglib/wavpack/wavpackproperties.h
1781index e6acdcc3..e169c5e4 100644
1782--- a/taglib/wavpack/wavpackproperties.h
1783+++ b/taglib/wavpack/wavpackproperties.h
1784@@ -58,13 +58,13 @@ namespace TagLib {
1785        * \deprecated This constructor will be dropped in favor of the one below
1786        * in a future version.
1787        */
1788-      TAGLIB_DEPRECATED Properties(const ByteVector &data, long streamLength,
1789+      TAGLIB_DEPRECATED Properties(const ByteVector &data, offset_t streamLength,
1790                                    ReadStyle style = Average);
1791
1792       /*!
1793        * Create an instance of WavPack::Properties.
1794        */
1795-      Properties(File *file, long streamLength, ReadStyle style = Average);
1796+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
1797
1798       /*!
1799        * Destroys this WavPack::Properties instance.
1800@@ -137,8 +137,8 @@ namespace TagLib {
1801       Properties(const Properties &);
1802       Properties &operator=(const Properties &);
1803
1804-      void read(File *file, long streamLength);
1805-      unsigned int seekFinalIndex(File *file, long streamLength);
1806+      void read(File *file, offset_t streamLength);
1807+      unsigned int seekFinalIndex(File *file, offset_t streamLength);
1808
1809       class PropertiesPrivate;
1810       PropertiesPrivate *d;
1811diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp
1812index 0455338d..09948166 100644
1813--- a/taglib/xm/xmfile.cpp
1814+++ b/taglib/xm/xmfile.cpp
1815@@ -586,7 +586,7 @@ void XM::File::read(bool)
1816     unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
1817     READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
1818
1819-    long offset = 0;
1820+    offset_t offset = 0;
1821     if(sampleCount > 0) {
1822       unsigned long sampleHeaderSize = 0;
1823       sumSampleCount += sampleCount;
1824