From 7f905ce9fa53a286f667d81c8d1dcaca35df5db6 Mon Sep 17 00:00:00 2001
From: Urs Fleisch <ufleisch@users.sourceforge.net>
Date: Sun, 19 Apr 2020 11:13:55 +0200
Subject: Support large files over 2GB

Backport of 4dcf0b41c687292e7b1263a679921c157ae2c22a
b01f45e141afa6a89aea319a2783f177e202fa1d
https://github.com/taglib/taglib/pull/77

diff --git a/taglib/ape/apefile.cpp b/taglib/ape/apefile.cpp
index a10c1f64..290836bd 100644
--- a/taglib/ape/apefile.cpp
+++ b/taglib/ape/apefile.cpp
@@ -69,13 +69,13 @@ public:
     delete properties;
   }
 
-  long APELocation;
+  offset_t APELocation;
   long APESize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   ID3v2::Header *ID3v2Header;
-  long ID3v2Location;
+  offset_t ID3v2Location;
   long ID3v2Size;
 
   TagUnion tag;
@@ -292,7 +292,7 @@ void APE::File::read(bool readProperties)
 
   if(readProperties) {
 
-    long streamLength;
+    offset_t streamLength;
 
     if(d->APELocation >= 0)
       streamLength = d->APELocation;
diff --git a/taglib/ape/apeproperties.cpp b/taglib/ape/apeproperties.cpp
index dee7e8c0..5a43445e 100644
--- a/taglib/ape/apeproperties.cpp
+++ b/taglib/ape/apeproperties.cpp
@@ -70,7 +70,7 @@ APE::Properties::Properties(File *, ReadStyle style) :
   debug("APE::Properties::Properties() -- This constructor is no longer used.");
 }
 
-APE::Properties::Properties(File *file, long streamLength, ReadStyle style) :
+APE::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
@@ -142,10 +142,10 @@ namespace
   }
 }
 
-void APE::Properties::read(File *file, long streamLength)
+void APE::Properties::read(File *file, offset_t streamLength)
 {
   // First, we assume that the file pointer is set at the first descriptor.
-  long offset = file->tell();
+  offset_t offset = file->tell();
   int version = headerVersion(file->readBlock(6));
 
   // Next, we look for the descriptor.
diff --git a/taglib/ape/apeproperties.h b/taglib/ape/apeproperties.h
index ebbf949b..d527815f 100644
--- a/taglib/ape/apeproperties.h
+++ b/taglib/ape/apeproperties.h
@@ -61,7 +61,7 @@ namespace TagLib {
        * Create an instance of APE::Properties with the data read from the
        * APE::File \a file.
        */
-      Properties(File *file, long streamLength, ReadStyle style = Average);
+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Destroys this APE::Properties instance.
@@ -129,7 +129,7 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void read(File *file, long streamLength);
+      void read(File *file, offset_t streamLength);
 
       void analyzeCurrent(File *file);
       void analyzeOld(File *file);
diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp
index 5d6c521b..b46b1791 100644
--- a/taglib/ape/apetag.cpp
+++ b/taglib/ape/apetag.cpp
@@ -80,7 +80,7 @@ public:
     footerLocation(0) {}
 
   File *file;
-  long footerLocation;
+  offset_t footerLocation;
 
   Footer footer;
   ItemListMap itemListMap;
@@ -95,7 +95,7 @@ APE::Tag::Tag() :
 {
 }
 
-APE::Tag::Tag(TagLib::File *file, long footerLocation) :
+APE::Tag::Tag(TagLib::File *file, offset_t footerLocation) :
   d(new TagPrivate())
 {
   d->file = file;
diff --git a/taglib/ape/apetag.h b/taglib/ape/apetag.h
index f4d4fba6..b5a2eb87 100644
--- a/taglib/ape/apetag.h
+++ b/taglib/ape/apetag.h
@@ -66,7 +66,7 @@ namespace TagLib {
        * Create an APE tag and parse the data in \a file with APE footer at
        * \a tagOffset.
        */
-      Tag(TagLib::File *file, long footerLocation);
+      Tag(TagLib::File *file, offset_t footerLocation);
 
       /*!
        * Destroys this Tag instance.
diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp
index a71d688b..b86d1883 100644
--- a/taglib/flac/flacfile.cpp
+++ b/taglib/flac/flacfile.cpp
@@ -79,10 +79,10 @@ public:
   }
 
   const ID3v2::FrameFactory *ID3v2FrameFactory;
-  long ID3v2Location;
+  offset_t ID3v2Location;
   long ID3v2OriginalSize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   TagUnion tag;
 
@@ -90,8 +90,8 @@ public:
   ByteVector xiphCommentData;
   BlockList blocks;
 
-  long flacStart;
-  long streamStart;
+  offset_t flacStart;
+  offset_t streamStart;
   bool scanned;
 };
 
@@ -341,7 +341,7 @@ ByteVector FLAC::File::streamInfoData()
   return ByteVector();
 }
 
-long FLAC::File::streamLength()
+offset_t FLAC::File::streamLength()
 {
   debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
   return 0;
@@ -456,7 +456,7 @@ void FLAC::File::read(bool readProperties)
 
     const ByteVector infoData = d->blocks.front()->render();
 
-    long streamLength;
+    offset_t streamLength;
 
     if(d->ID3v1Location >= 0)
       streamLength = d->ID3v1Location - d->streamStart;
@@ -477,7 +477,7 @@ void FLAC::File::scan()
   if(!isValid())
     return;
 
-  long nextBlockOffset;
+  offset_t nextBlockOffset;
 
   if(d->ID3v2Location >= 0)
     nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h
index 1b8654eb..9a2422f2 100644
--- a/taglib/flac/flacfile.h
+++ b/taglib/flac/flacfile.h
@@ -256,7 +256,7 @@ namespace TagLib {
        *
        * \deprecated Always returns zero.
        */
-      TAGLIB_DEPRECATED long streamLength();  // BIC: remove
+      TAGLIB_DEPRECATED offset_t streamLength();  // BIC: remove
 
       /*!
        * Returns a list of pictures attached to the FLAC file.
diff --git a/taglib/flac/flacproperties.cpp b/taglib/flac/flacproperties.cpp
index b947f039..a798940a 100644
--- a/taglib/flac/flacproperties.cpp
+++ b/taglib/flac/flacproperties.cpp
@@ -55,7 +55,7 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
+FLAC::Properties::Properties(ByteVector data, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
@@ -128,7 +128,7 @@ ByteVector FLAC::Properties::signature() const
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void FLAC::Properties::read(const ByteVector &data, long streamLength)
+void FLAC::Properties::read(const ByteVector &data, offset_t streamLength)
 {
   if(data.size() < 18) {
     debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
diff --git a/taglib/flac/flacproperties.h b/taglib/flac/flacproperties.h
index 743e5872..75e8ecb4 100644
--- a/taglib/flac/flacproperties.h
+++ b/taglib/flac/flacproperties.h
@@ -50,7 +50,7 @@ namespace TagLib {
        * ByteVector \a data.
        */
        // BIC: switch to const reference
-      Properties(ByteVector data, long streamLength, ReadStyle style = Average);
+      Properties(ByteVector data, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Create an instance of FLAC::Properties with the data read from the
@@ -137,7 +137,7 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void read(const ByteVector &data, long streamLength);
+      void read(const ByteVector &data, offset_t streamLength);
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp
index e030579f..78f5acbb 100644
--- a/taglib/mp4/mp4atom.cpp
+++ b/taglib/mp4/mp4atom.cpp
@@ -156,7 +156,7 @@ MP4::Atoms::Atoms(File *file)
   atoms.setAutoDelete(true);
 
   file->seek(0, File::End);
-  long end = file->tell();
+  offset_t end = file->tell();
   file->seek(0);
   while(file->tell() + 8 <= end) {
     MP4::Atom *atom = new MP4::Atom(file);
diff --git a/taglib/mp4/mp4atom.h b/taglib/mp4/mp4atom.h
index 5e234cce..ee2ad6fb 100644
--- a/taglib/mp4/mp4atom.h
+++ b/taglib/mp4/mp4atom.h
@@ -82,8 +82,8 @@ namespace TagLib {
       Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
       bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
       AtomList findall(const char *name, bool recursive = false);
-      long offset;
-      long length;
+      offset_t offset;
+      offset_t length;
       TagLib::ByteVector name;
       AtomList children;
     private:
diff --git a/taglib/mp4/mp4tag.cpp b/taglib/mp4/mp4tag.cpp
index 758475b9..9e6ebe19 100644
--- a/taglib/mp4/mp4tag.cpp
+++ b/taglib/mp4/mp4tag.cpp
@@ -583,7 +583,7 @@ MP4::Tag::updateParents(const AtomList &path, long delta, int ignore)
 }
 
 void
-MP4::Tag::updateOffsets(long delta, long offset)
+MP4::Tag::updateOffsets(long delta, offset_t offset)
 {
   MP4::Atom *moov = d->atoms->find("moov");
   if(moov) {
@@ -667,7 +667,7 @@ MP4::Tag::saveNew(ByteVector data)
     data = renderAtom("udta", data);
   }
 
-  long offset = path.back()->offset + 8;
+  offset_t offset = path.back()->offset + 8;
   d->file->insert(data, offset, 0);
 
   updateParents(path, data.size());
@@ -685,8 +685,8 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
   AtomList::ConstIterator it = path.end();
 
   MP4::Atom *ilst = *(--it);
-  long offset = ilst->offset;
-  long length = ilst->length;
+  offset_t offset = ilst->offset;
+  offset_t length = ilst->length;
 
   MP4::Atom *meta = *(--it);
   AtomList::ConstIterator index = meta->children.find(ilst);
diff --git a/taglib/mp4/mp4tag.h b/taglib/mp4/mp4tag.h
index 2f551140..8a3308bb 100644
--- a/taglib/mp4/mp4tag.h
+++ b/taglib/mp4/mp4tag.h
@@ -151,7 +151,7 @@ namespace TagLib {
         ByteVector renderCovr(const ByteVector &name, const Item &item) const;
 
         void updateParents(const AtomList &path, long delta, int ignore = 0);
-        void updateOffsets(long delta, long offset);
+        void updateOffsets(long delta, offset_t offset);
 
         void saveNew(ByteVector data);
         void saveExisting(ByteVector data, const AtomList &path);
diff --git a/taglib/mpc/mpcfile.cpp b/taglib/mpc/mpcfile.cpp
index 0ffaf893..0e36a1f8 100644
--- a/taglib/mpc/mpcfile.cpp
+++ b/taglib/mpc/mpcfile.cpp
@@ -61,13 +61,13 @@ public:
     delete properties;
   }
 
-  long APELocation;
+  offset_t APELocation;
   long APESize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   ID3v2::Header *ID3v2Header;
-  long ID3v2Location;
+  offset_t ID3v2Location;
   long ID3v2Size;
 
   TagUnion tag;
@@ -310,7 +310,7 @@ void MPC::File::read(bool readProperties)
 
   if(readProperties) {
 
-    long streamLength;
+    offset_t streamLength;
 
     if(d->APELocation >= 0)
       streamLength = d->APELocation;
diff --git a/taglib/mpc/mpcproperties.cpp b/taglib/mpc/mpcproperties.cpp
index effaabed..724e5c7d 100644
--- a/taglib/mpc/mpcproperties.cpp
+++ b/taglib/mpc/mpcproperties.cpp
@@ -66,14 +66,14 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
+MPC::Properties::Properties(const ByteVector &data, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
   readSV7(data, streamLength);
 }
 
-MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
+MPC::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
@@ -203,7 +203,7 @@ namespace
   const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
 }  // namespace
 
-void MPC::Properties::readSV8(File *file, long streamLength)
+void MPC::Properties::readSV8(File *file, offset_t streamLength)
 {
   bool readSH = false, readRG = false;
 
@@ -295,7 +295,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
   }
 }
 
-void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
+void MPC::Properties::readSV7(const ByteVector &data, offset_t streamLength)
 {
   if(data.startsWith("MP+")) {
     if(data.size() < 4)
diff --git a/taglib/mpc/mpcproperties.h b/taglib/mpc/mpcproperties.h
index 9a902dc9..439de74e 100644
--- a/taglib/mpc/mpcproperties.h
+++ b/taglib/mpc/mpcproperties.h
@@ -53,13 +53,13 @@ namespace TagLib {
        *
        * This constructor is deprecated. It only works for MPC version up to 7.
        */
-      Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
+      Properties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Create an instance of MPC::Properties with the data read directly
        * from a MPC::File.
        */
-      Properties(File *file, long streamLength, ReadStyle style = Average);
+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Destroys this MPC::Properties instance.
@@ -146,8 +146,8 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void readSV7(const ByteVector &data, long streamLength);
-      void readSV8(File *file, long streamLength);
+      void readSV7(const ByteVector &data, offset_t streamLength);
+      void readSV8(File *file, offset_t streamLength);
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
diff --git a/taglib/mpeg/id3v1/id3v1tag.cpp b/taglib/mpeg/id3v1/id3v1tag.cpp
index 358a9595..24ac1794 100644
--- a/taglib/mpeg/id3v1/id3v1tag.cpp
+++ b/taglib/mpeg/id3v1/id3v1tag.cpp
@@ -48,7 +48,7 @@ public:
     genre(255) {}
 
   File *file;
-  long tagOffset;
+  offset_t tagOffset;
 
   String title;
   String artist;
@@ -88,7 +88,7 @@ ID3v1::Tag::Tag() :
 {
 }
 
-ID3v1::Tag::Tag(File *file, long tagOffset) :
+ID3v1::Tag::Tag(File *file, offset_t tagOffset) :
   d(new TagPrivate())
 {
   d->file = file;
diff --git a/taglib/mpeg/id3v1/id3v1tag.h b/taglib/mpeg/id3v1/id3v1tag.h
index b61f06af..55ab63ff 100644
--- a/taglib/mpeg/id3v1/id3v1tag.h
+++ b/taglib/mpeg/id3v1/id3v1tag.h
@@ -114,7 +114,7 @@ namespace TagLib {
        * Create an ID3v1 tag and parse the data in \a file starting at
        * \a tagOffset.
        */
-      Tag(File *file, long tagOffset);
+      Tag(File *file, offset_t tagOffset);
 
       /*!
        * Destroys this Tag instance.
diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp
index 156c6d5e..2c1e8a72 100644
--- a/taglib/mpeg/id3v2/id3v2tag.cpp
+++ b/taglib/mpeg/id3v2/id3v2tag.cpp
@@ -88,7 +88,7 @@ public:
   const FrameFactory *factory;
 
   File *file;
-  long tagOffset;
+  offset_t tagOffset;
 
   Header header;
   ExtendedHeader *extendedHeader;
@@ -125,7 +125,7 @@ ID3v2::Tag::Tag() :
   d->factory = FrameFactory::instance();
 }
 
-ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
+ID3v2::Tag::Tag(File *file, offset_t tagOffset, const FrameFactory *factory) :
   d(new TagPrivate())
 {
   d->factory = factory;
diff --git a/taglib/mpeg/id3v2/id3v2tag.h b/taglib/mpeg/id3v2/id3v2tag.h
index 74d1df1e..60b5c2e8 100644
--- a/taglib/mpeg/id3v2/id3v2tag.h
+++ b/taglib/mpeg/id3v2/id3v2tag.h
@@ -146,7 +146,7 @@ namespace TagLib {
        *
        * \see FrameFactory
        */
-      Tag(File *file, long tagOffset,
+      Tag(File *file, offset_t tagOffset,
           const FrameFactory *factory = FrameFactory::instance());
 
       /*!
diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp
index 5f14e49d..da64f6ea 100644
--- a/taglib/mpeg/mpegfile.cpp
+++ b/taglib/mpeg/mpegfile.cpp
@@ -63,13 +63,13 @@ public:
 
   const ID3v2::FrameFactory *ID3v2FrameFactory;
 
-  long ID3v2Location;
+  offset_t ID3v2Location;
   long ID3v2OriginalSize;
 
-  long APELocation;
+  offset_t APELocation;
   long APEOriginalSize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   TagUnion tag;
 
@@ -105,13 +105,13 @@ bool MPEG::File::isSupported(IOStream *stream)
   // MPEG frame headers are really confusing with irrelevant binary data.
   // So we check if a frame header is really valid.
 
-  long headerOffset;
+  offset_t headerOffset;
   const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true, &headerOffset);
 
   if(buffer.isEmpty())
       return false;
 
-  const long originalPosition = stream->tell();
+  const offset_t originalPosition = stream->tell();
   AdapterFile file(stream);
 
   for(unsigned int i = 0; i < buffer.size() - 1; ++i) {
@@ -406,7 +406,7 @@ void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
   d->ID3v2FrameFactory = factory;
 }
 
-long MPEG::File::nextFrameOffset(long position)
+offset_t MPEG::File::nextFrameOffset(offset_t position)
 {
   ByteVector frameSyncBytes(2, '\0');
 
@@ -430,7 +430,7 @@ long MPEG::File::nextFrameOffset(long position)
   }
 }
 
-long MPEG::File::previousFrameOffset(long position)
+offset_t MPEG::File::previousFrameOffset(offset_t position)
 {
   ByteVector frameSyncBytes(2, '\0');
 
@@ -455,7 +455,7 @@ long MPEG::File::previousFrameOffset(long position)
   return -1;
 }
 
-long MPEG::File::firstFrameOffset()
+offset_t MPEG::File::firstFrameOffset()
 {
   long position = 0;
 
@@ -465,9 +465,9 @@ long MPEG::File::firstFrameOffset()
   return nextFrameOffset(position);
 }
 
-long MPEG::File::lastFrameOffset()
+offset_t MPEG::File::lastFrameOffset()
 {
-  long position;
+  offset_t position;
 
   if(hasAPETag())
     position = d->APELocation - 1;
@@ -535,7 +535,7 @@ void MPEG::File::read(bool readProperties)
   ID3v1Tag(true);
 }
 
-long MPEG::File::findID3v2()
+offset_t MPEG::File::findID3v2()
 {
   if(!isValid())
     return -1;
diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h
index 3fcb7272..685f5054 100644
--- a/taglib/mpeg/mpegfile.h
+++ b/taglib/mpeg/mpegfile.h
@@ -322,24 +322,24 @@ namespace TagLib {
       /*!
        * Returns the position in the file of the first MPEG frame.
        */
-      long firstFrameOffset();
+      offset_t firstFrameOffset();
 
       /*!
        * Returns the position in the file of the next MPEG frame,
        * using the current position as start
        */
-      long nextFrameOffset(long position);
+      offset_t nextFrameOffset(offset_t position);
 
       /*!
        * Returns the position in the file of the previous MPEG frame,
        * using the current position as start
        */
-      long previousFrameOffset(long position);
+      offset_t previousFrameOffset(offset_t position);
 
       /*!
        * Returns the position in the file of the last MPEG frame.
        */
-      long lastFrameOffset();
+      offset_t lastFrameOffset();
 
       /*!
        * Returns whether or not the file on disk actually has an ID3v1 tag.
@@ -376,7 +376,7 @@ namespace TagLib {
       File &operator=(const File &);
 
       void read(bool readProperties);
-      long findID3v2();
+      offset_t findID3v2();
 
       class FilePrivate;
       FilePrivate *d;
diff --git a/taglib/mpeg/mpegheader.cpp b/taglib/mpeg/mpegheader.cpp
index 5a5015d6..b9405008 100644
--- a/taglib/mpeg/mpegheader.cpp
+++ b/taglib/mpeg/mpegheader.cpp
@@ -75,7 +75,7 @@ MPEG::Header::Header(const ByteVector &data) :
   debug("MPEG::Header::Header() - This constructor is no longer used.");
 }
 
-MPEG::Header::Header(File *file, long offset, bool checkLength) :
+MPEG::Header::Header(File *file, offset_t offset, bool checkLength) :
   d(new HeaderPrivate())
 {
   parse(file, offset, checkLength);
@@ -170,7 +170,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h)
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void MPEG::Header::parse(File *file, long offset, bool checkLength)
+void MPEG::Header::parse(File *file, offset_t offset, bool checkLength)
 {
   file->seek(offset);
   const ByteVector data = file->readBlock(4);
diff --git a/taglib/mpeg/mpegheader.h b/taglib/mpeg/mpegheader.h
index ca51184c..3fb214e5 100644
--- a/taglib/mpeg/mpegheader.h
+++ b/taglib/mpeg/mpegheader.h
@@ -61,7 +61,7 @@ namespace TagLib {
        * check if the frame length is parsed and calculated correctly.  So it's
        * suitable for seeking for the first valid frame.
        */
-      Header(File *file, long offset, bool checkLength = true);
+      Header(File *file, offset_t offset, bool checkLength = true);
 
       /*!
        * Does a shallow copy of \a h.
@@ -167,7 +167,7 @@ namespace TagLib {
       Header &operator=(const Header &h);
 
     private:
-      void parse(File *file, long offset, bool checkLength);
+      void parse(File *file, offset_t offset, bool checkLength);
 
       class HeaderPrivate;
       HeaderPrivate *d;
diff --git a/taglib/mpeg/mpegproperties.cpp b/taglib/mpeg/mpegproperties.cpp
index 5eec84f7..d66f8ab1 100644
--- a/taglib/mpeg/mpegproperties.cpp
+++ b/taglib/mpeg/mpegproperties.cpp
@@ -157,7 +157,7 @@ void MPEG::Properties::read(File *file)
 {
   // Only the first valid frame is required if we have a VBR header.
 
-  const long firstFrameOffset = file->firstFrameOffset();
+  const offset_t firstFrameOffset = file->firstFrameOffset();
   if(firstFrameOffset < 0) {
     debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
     return;
@@ -197,14 +197,14 @@ void MPEG::Properties::read(File *file)
 
     // Look for the last MPEG audio frame to calculate the stream length.
 
-    const long lastFrameOffset = file->lastFrameOffset();
+    const offset_t lastFrameOffset = file->lastFrameOffset();
     if(lastFrameOffset < 0) {
       debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
     }
     else
     {
       const Header lastHeader(file, lastFrameOffset, false);
-      const long streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
+      const offset_t streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
       if (streamLength > 0)
         d->length = static_cast<int>(streamLength * 8.0 / d->bitrate + 0.5);
     }
diff --git a/taglib/ogg/flac/oggflacfile.cpp b/taglib/ogg/flac/oggflacfile.cpp
index 07ea9dcc..5c2f95c6 100644
--- a/taglib/ogg/flac/oggflacfile.cpp
+++ b/taglib/ogg/flac/oggflacfile.cpp
@@ -58,8 +58,8 @@ public:
   Properties *properties;
   ByteVector streamInfoData;
   ByteVector xiphCommentData;
-  long streamStart;
-  long streamLength;
+  offset_t streamStart;
+  offset_t streamLength;
   bool scanned;
 
   bool hasXiphComment;
@@ -206,7 +206,7 @@ ByteVector Ogg::FLAC::File::xiphCommentData()
   return d->xiphCommentData;
 }
 
-long Ogg::FLAC::File::streamLength()
+offset_t Ogg::FLAC::File::streamLength()
 {
   scan();
   return d->streamLength;
@@ -223,7 +223,7 @@ void Ogg::FLAC::File::scan()
     return;
 
   int ipacket = 0;
-  long overhead = 0;
+  offset_t overhead = 0;
 
   ByteVector metadataHeader = packet(ipacket);
   if(metadataHeader.isEmpty())
diff --git a/taglib/ogg/flac/oggflacfile.h b/taglib/ogg/flac/oggflacfile.h
index b2686e45..0e5e1ac4 100644
--- a/taglib/ogg/flac/oggflacfile.h
+++ b/taglib/ogg/flac/oggflacfile.h
@@ -134,7 +134,7 @@ namespace TagLib {
        * Returns the length of the audio-stream, used by FLAC::Properties for
        * calculating the bitrate.
        */
-      long streamLength();
+      offset_t streamLength();
 
       /*!
        * Returns whether or not the file on disk actually has a XiphComment.
diff --git a/taglib/ogg/oggfile.cpp b/taglib/ogg/oggfile.cpp
index 1f2cce93..05059ec8 100644
--- a/taglib/ogg/oggfile.cpp
+++ b/taglib/ogg/oggfile.cpp
@@ -129,7 +129,7 @@ void Ogg::File::setPacket(unsigned int i, const ByteVector &p)
 const Ogg::PageHeader *Ogg::File::firstPageHeader()
 {
   if(!d->firstPageHeader) {
-    const long firstPageHeaderOffset = find("OggS");
+    const offset_t firstPageHeaderOffset = find("OggS");
     if(firstPageHeaderOffset < 0)
       return 0;
 
@@ -142,7 +142,7 @@ const Ogg::PageHeader *Ogg::File::firstPageHeader()
 const Ogg::PageHeader *Ogg::File::lastPageHeader()
 {
   if(!d->lastPageHeader) {
-    const long lastPageHeaderOffset = rfind("OggS");
+    const offset_t lastPageHeaderOffset = rfind("OggS");
     if(lastPageHeaderOffset < 0)
       return 0;
 
@@ -192,7 +192,7 @@ bool Ogg::File::readPages(unsigned int i)
 {
   while(true) {
     unsigned int packetIndex;
-    long offset;
+    offset_t offset;
 
     if(d->pages.isEmpty()) {
       packetIndex = 0;
@@ -275,8 +275,8 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
   for(it = pages.begin(); it != pages.end(); ++it)
     data.append((*it)->render());
 
-  const unsigned long originalOffset = firstPage->fileOffset();
-  const unsigned long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
+  const offset_t originalOffset = firstPage->fileOffset();
+  const offset_t originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
 
   insert(data, originalOffset, originalLength);
 
diff --git a/taglib/ogg/oggpage.cpp b/taglib/ogg/oggpage.cpp
index 8cd15a5c..d43b0194 100644
--- a/taglib/ogg/oggpage.cpp
+++ b/taglib/ogg/oggpage.cpp
@@ -37,14 +37,14 @@ using namespace TagLib;
 class Ogg::Page::PagePrivate
 {
 public:
-  PagePrivate(File *f = 0, long pageOffset = -1) :
+  PagePrivate(File *f = 0, offset_t pageOffset = -1) :
     file(f),
     fileOffset(pageOffset),
     header(f, pageOffset),
     firstPacketIndex(-1) {}
 
   File *file;
-  long fileOffset;
+  offset_t fileOffset;
   PageHeader header;
   int firstPacketIndex;
   ByteVectorList packets;
@@ -54,7 +54,7 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-Ogg::Page::Page(Ogg::File *file, long pageOffset) :
+Ogg::Page::Page(Ogg::File *file, offset_t pageOffset) :
   d(new PagePrivate(file, pageOffset))
 {
 }
@@ -64,7 +64,7 @@ Ogg::Page::~Page()
   delete d;
 }
 
-long Ogg::Page::fileOffset() const
+offset_t Ogg::Page::fileOffset() const
 {
   return d->fileOffset;
 }
diff --git a/taglib/ogg/oggpage.h b/taglib/ogg/oggpage.h
index af3fe2c9..3df200e8 100644
--- a/taglib/ogg/oggpage.h
+++ b/taglib/ogg/oggpage.h
@@ -55,14 +55,14 @@ namespace TagLib {
       /*!
        * Read an Ogg page from the \a file at the position \a pageOffset.
        */
-      Page(File *file, long pageOffset);
+      Page(File *file, offset_t pageOffset);
 
       virtual ~Page();
 
       /*!
        * Returns the page's position within the file (in bytes).
        */
-      long fileOffset() const;
+      offset_t fileOffset() const;
 
       /*!
        * Returns a pointer to the header for this page.  This pointer will become
diff --git a/taglib/ogg/oggpageheader.cpp b/taglib/ogg/oggpageheader.cpp
index b867567c..cc645eaf 100644
--- a/taglib/ogg/oggpageheader.cpp
+++ b/taglib/ogg/oggpageheader.cpp
@@ -66,7 +66,7 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) :
+Ogg::PageHeader::PageHeader(Ogg::File *file, offset_t pageOffset) :
   d(new PageHeaderPrivate())
 {
   if(file && pageOffset >= 0)
@@ -225,7 +225,7 @@ ByteVector Ogg::PageHeader::render() const
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
+void Ogg::PageHeader::read(Ogg::File *file, offset_t pageOffset)
 {
   file->seek(pageOffset);
 
diff --git a/taglib/ogg/oggpageheader.h b/taglib/ogg/oggpageheader.h
index 571155fc..d6c714c1 100644
--- a/taglib/ogg/oggpageheader.h
+++ b/taglib/ogg/oggpageheader.h
@@ -52,7 +52,7 @@ namespace TagLib {
        * create a page with no (and as such, invalid) data that must be set
        * later.
        */
-      PageHeader(File *file = 0, long pageOffset = -1);
+      PageHeader(File *file = 0, offset_t pageOffset = -1);
 
       /*!
        * Deletes this instance of the PageHeader.
@@ -219,7 +219,7 @@ namespace TagLib {
       PageHeader(const PageHeader &);
       PageHeader &operator=(const PageHeader &);
 
-      void read(Ogg::File *file, long pageOffset);
+      void read(Ogg::File *file, offset_t pageOffset);
       ByteVector lacingValues() const;
 
       class PageHeaderPrivate;
diff --git a/taglib/ogg/opus/opusproperties.cpp b/taglib/ogg/opus/opusproperties.cpp
index b60cc01d..e19ab64d 100644
--- a/taglib/ogg/opus/opusproperties.cpp
+++ b/taglib/ogg/opus/opusproperties.cpp
@@ -163,7 +163,7 @@ void Opus::Properties::read(File *file)
 
       if(frameCount > 0) {
         const double length = frameCount * 1000.0 / 48000.0;
-        long fileLengthWithoutOverhead = file->length();
+        offset_t fileLengthWithoutOverhead = file->length();
         // Ignore the two mandatory header packets, see "3. Packet Organization"
         // in https://tools.ietf.org/html/rfc7845.html
         for (unsigned int i = 0; i < 2; ++i) {
diff --git a/taglib/ogg/speex/speexproperties.cpp b/taglib/ogg/speex/speexproperties.cpp
index b7a11cc6..fae184a0 100644
--- a/taglib/ogg/speex/speexproperties.cpp
+++ b/taglib/ogg/speex/speexproperties.cpp
@@ -182,7 +182,7 @@ void Speex::Properties::read(File *file)
 
       if(frameCount > 0) {
         const double length = frameCount * 1000.0 / d->sampleRate;
-        long fileLengthWithoutOverhead = file->length();
+        offset_t fileLengthWithoutOverhead = file->length();
         // Ignore the two header packets, see "Ogg file format" in
         // https://www.speex.org/docs/manual/speex-manual/node8.html
         for (unsigned int i = 0; i < 2; ++i) {
diff --git a/taglib/ogg/vorbis/vorbisproperties.cpp b/taglib/ogg/vorbis/vorbisproperties.cpp
index 4000c254..6f6c8907 100644
--- a/taglib/ogg/vorbis/vorbisproperties.cpp
+++ b/taglib/ogg/vorbis/vorbisproperties.cpp
@@ -186,7 +186,7 @@ void Vorbis::Properties::read(File *file)
 
       if(frameCount > 0) {
         const double length = frameCount * 1000.0 / d->sampleRate;
-        long fileLengthWithoutOverhead = file->length();
+        offset_t fileLengthWithoutOverhead = file->length();
         // Ignore the three initial header packets, see "1.3.1. Decode Setup" in
         // https://xiph.org/vorbis/doc/Vorbis_I_spec.html
         for (unsigned int i = 0; i < 3; ++i) {
diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp
index 005551f4..87ce7240 100644
--- a/taglib/riff/rifffile.cpp
+++ b/taglib/riff/rifffile.cpp
@@ -38,7 +38,7 @@ using namespace TagLib;
 struct Chunk
 {
   ByteVector   name;
-  unsigned int offset;
+  offset_t offset;
   unsigned int size;
   unsigned int padding;
 };
@@ -54,7 +54,7 @@ public:
   const Endianness endianness;
 
   unsigned int size;
-  long sizeOffset;
+  offset_t sizeOffset;
 
   std::vector<Chunk> chunks;
 };
@@ -108,7 +108,7 @@ unsigned int RIFF::File::chunkDataSize(unsigned int i) const
   return d->chunks[i].size;
 }
 
-unsigned int RIFF::File::chunkOffset(unsigned int i) const
+offset_t RIFF::File::chunkOffset(unsigned int i) const
 {
   if(i >= d->chunks.size()) {
     debug("RIFF::File::chunkOffset() - Index out of range. Returning 0.");
@@ -212,7 +212,7 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
 
   Chunk &last = d->chunks.back();
 
-  long offset = last.offset + last.size + last.padding;
+  offset_t offset = last.offset + last.size + last.padding;
   if(offset & 1) {
     if(last.padding == 1) {
       last.padding = 0; // This should not happen unless the file is corrupted.
@@ -283,7 +283,7 @@ void RIFF::File::read()
 {
   const bool bigEndian = (d->endianness == BigEndian);
 
-  long offset = tell();
+  offset_t offset = tell();
 
   offset += 4;
   d->sizeOffset = offset;
@@ -345,7 +345,7 @@ void RIFF::File::read()
 }
 
 void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
-                            unsigned long offset, unsigned long replace)
+                            offset_t offset, unsigned long replace)
 {
   ByteVector combined;
 
diff --git a/taglib/riff/rifffile.h b/taglib/riff/rifffile.h
index 5c606b4a..cf821baf 100644
--- a/taglib/riff/rifffile.h
+++ b/taglib/riff/rifffile.h
@@ -71,7 +71,7 @@ namespace TagLib {
       /*!
        * \return The offset within the file for the selected chunk number.
        */
-      unsigned int chunkOffset(unsigned int i) const;
+      offset_t chunkOffset(unsigned int i) const;
 
       /*!
        * \return The size of the chunk data.
@@ -145,7 +145,7 @@ namespace TagLib {
 
       void read();
       void writeChunk(const ByteVector &name, const ByteVector &data,
-                      unsigned long offset, unsigned long replace = 0);
+                      offset_t offset, unsigned long replace = 0);
 
       /*!
        * Update the global RIFF size based on the current internal structure.
diff --git a/taglib/tagutils.cpp b/taglib/tagutils.cpp
index d6d92406..82dc2fa2 100644
--- a/taglib/tagutils.cpp
+++ b/taglib/tagutils.cpp
@@ -33,13 +33,13 @@
 
 using namespace TagLib;
 
-long Utils::findID3v1(File *file)
+offset_t Utils::findID3v1(File *file)
 {
   if(!file->isValid())
     return -1;
 
   file->seek(-128, File::End);
-  const long p = file->tell();
+  const offset_t p = file->tell();
 
   if(file->readBlock(3) == ID3v1::Tag::fileIdentifier())
     return p;
@@ -47,7 +47,7 @@ long Utils::findID3v1(File *file)
   return -1;
 }
 
-long Utils::findID3v2(File *file)
+offset_t Utils::findID3v2(File *file)
 {
   if(!file->isValid())
     return -1;
@@ -60,7 +60,7 @@ long Utils::findID3v2(File *file)
   return -1;
 }
 
-long Utils::findAPE(File *file, long id3v1Location)
+offset_t Utils::findAPE(File *file, offset_t id3v1Location)
 {
   if(!file->isValid())
     return -1;
@@ -70,7 +70,7 @@ long Utils::findAPE(File *file, long id3v1Location)
   else
     file->seek(-32, File::End);
 
-  const long p = file->tell();
+  const offset_t p = file->tell();
 
   if(file->readBlock(8) == APE::Tag::fileIdentifier())
     return p;
@@ -79,13 +79,13 @@ long Utils::findAPE(File *file, long id3v1Location)
 }
 
 ByteVector TagLib::Utils::readHeader(IOStream *stream, unsigned int length,
-                                     bool skipID3v2, long *headerOffset)
+                                     bool skipID3v2, offset_t *headerOffset)
 {
   if(!stream || !stream->isOpen())
     return ByteVector();
 
-  const long originalPosition = stream->tell();
-  long bufferOffset = 0;
+  const offset_t originalPosition = stream->tell();
+  offset_t bufferOffset = 0;
 
   if(skipID3v2) {
     stream->seek(0);
diff --git a/taglib/tagutils.h b/taglib/tagutils.h
index 4488a32b..47d77246 100644
--- a/taglib/tagutils.h
+++ b/taglib/tagutils.h
@@ -39,14 +39,14 @@ namespace TagLib {
 
   namespace Utils {
 
-    long findID3v1(File *file);
+    offset_t findID3v1(File *file);
 
-    long findID3v2(File *file);
+    offset_t findID3v2(File *file);
 
-    long findAPE(File *file, long id3v1Location);
+    offset_t findAPE(File *file, offset_t id3v1Location);
 
     ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2,
-                          long *headerOffset = 0);
+                          offset_t *headerOffset = 0);
   }
 }
 
diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h
index ffce61f7..c7125d3e 100644
--- a/taglib/toolkit/taglib.h
+++ b/taglib/toolkit/taglib.h
@@ -54,6 +54,11 @@
 #define TAGLIB_DEPRECATED
 #endif
 
+#define TAGLIB_WITH_OFFSET_TYPE
+#ifndef _WIN32
+#include <sys/types.h>
+#endif
+
 #include <string>
 
 //! A namespace for all TagLib related classes and functions
@@ -79,6 +84,14 @@ namespace TagLib {
   typedef unsigned long      ulong;
   typedef unsigned long long ulonglong;
 
+  // Offset or length type for I/O streams.
+  // In Win32, always 64bit. Otherwise, equivalent to off_t.
+#ifdef _WIN32
+  typedef long long offset_t;
+#else
+  typedef off_t     offset_t;
+#endif
+
   /*!
    * Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3)
    * so I'm providing something here that should be constant.
diff --git a/taglib/toolkit/tbytevectorstream.cpp b/taglib/toolkit/tbytevectorstream.cpp
index 333f528c..978fb23f 100644
--- a/taglib/toolkit/tbytevectorstream.cpp
+++ b/taglib/toolkit/tbytevectorstream.cpp
@@ -40,7 +40,7 @@ public:
   ByteVectorStreamPrivate(const ByteVector &data);
 
   ByteVector data;
-  long position;
+  offset_t position;
 };
 
 ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) :
@@ -88,7 +88,7 @@ void ByteVectorStream::writeBlock(const ByteVector &data)
   d->position += size;
 }
 
-void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
+void ByteVectorStream::insert(const ByteVector &data, offset_t start, unsigned long replace)
 {
   long sizeDiff = data.size() - replace;
   if(sizeDiff < 0) {
@@ -96,19 +96,19 @@ void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsig
   }
   else if(sizeDiff > 0) {
     truncate(length() + sizeDiff);
-    unsigned long readPosition  = start + replace;
-    unsigned long writePosition = start + data.size();
+    offset_t readPosition  = start + replace;
+    offset_t writePosition = start + data.size();
     memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition);
   }
   seek(start);
   writeBlock(data);
 }
 
-void ByteVectorStream::removeBlock(unsigned long start, unsigned long length)
+void ByteVectorStream::removeBlock(offset_t start, unsigned long length)
 {
-  unsigned long readPosition = start + length;
-  unsigned long writePosition = start;
-  if(readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
+  offset_t readPosition = start + length;
+  offset_t writePosition = start;
+  if(readPosition < ByteVectorStream::length()) {
     unsigned long bytesToMove = ByteVectorStream::length() - readPosition;
     memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove);
     writePosition += bytesToMove;
@@ -127,7 +127,7 @@ bool ByteVectorStream::isOpen() const
   return true;
 }
 
-void ByteVectorStream::seek(long offset, Position p)
+void ByteVectorStream::seek(offset_t offset, Position p)
 {
   switch(p) {
   case Beginning:
@@ -146,17 +146,17 @@ void ByteVectorStream::clear()
 {
 }
 
-long ByteVectorStream::tell() const
+offset_t ByteVectorStream::tell() const
 {
   return d->position;
 }
 
-long ByteVectorStream::length()
+offset_t ByteVectorStream::length()
 {
   return d->data.size();
 }
 
-void ByteVectorStream::truncate(long length)
+void ByteVectorStream::truncate(offset_t length)
 {
   d->data.resize(length);
 }
diff --git a/taglib/toolkit/tbytevectorstream.h b/taglib/toolkit/tbytevectorstream.h
index 84327c46..78ebfd4a 100644
--- a/taglib/toolkit/tbytevectorstream.h
+++ b/taglib/toolkit/tbytevectorstream.h
@@ -81,7 +81,7 @@ namespace TagLib {
      * \note This method is slow since it requires rewriting all of the file
      * after the insertion point.
      */
-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
 
     /*!
      * Removes a block of the file starting a \a start and continuing for
@@ -90,7 +90,7 @@ namespace TagLib {
      * \note This method is slow since it involves rewriting all of the file
      * after the removed portion.
      */
-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
+    void removeBlock(offset_t start = 0, unsigned long length = 0);
 
     /*!
      * Returns true if the file is read only (or if the file can not be opened).
@@ -109,7 +109,7 @@ namespace TagLib {
      *
      * \see Position
      */
-    void seek(long offset, Position p = Beginning);
+    void seek(offset_t offset, Position p = Beginning);
 
     /*!
      * Reset the end-of-file and error flags on the file.
@@ -119,17 +119,17 @@ namespace TagLib {
     /*!
      * Returns the current offset within the file.
      */
-    long tell() const;
+    offset_t tell() const;
 
     /*!
      * Returns the length of the file.
      */
-    long length();
+    offset_t length();
 
     /*!
      * Truncates the file to a \a length.
      */
-    void truncate(long length);
+    void truncate(offset_t length);
 
     ByteVector *data();
 
diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp
index b7d0be4d..be2bf39e 100644
--- a/taglib/toolkit/tfile.cpp
+++ b/taglib/toolkit/tfile.cpp
@@ -232,14 +232,14 @@ void File::writeBlock(const ByteVector &data)
   d->stream->writeBlock(data);
 }
 
-long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before)
+offset_t File::find(const ByteVector &pattern, offset_t fromOffset, const ByteVector &before)
 {
   if(!d->stream || pattern.size() > bufferSize())
       return -1;
 
   // The position in the file that the current buffer starts at.
 
-  long bufferOffset = fromOffset;
+  offset_t bufferOffset = fromOffset;
   ByteVector buffer;
 
   // These variables are used to keep track of a partial match that happens at
@@ -251,7 +251,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
   // Save the location of the current read pointer.  We will restore the
   // position using seek() before all returns.
 
-  long originalPosition = tell();
+  offset_t originalPosition = tell();
 
   // Start the search at the offset.
 
@@ -328,7 +328,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
 }
 
 
-long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before)
+offset_t File::rfind(const ByteVector &pattern, offset_t fromOffset, const ByteVector &before)
 {
   if(!d->stream || pattern.size() > bufferSize())
       return -1;
@@ -348,7 +348,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
   // Save the location of the current read pointer.  We will restore the
   // position using seek() before all returns.
 
-  long originalPosition = tell();
+  offset_t originalPosition = tell();
 
   // Start the search at the offset.
 
@@ -356,7 +356,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
     fromOffset = length();
 
   long bufferLength = bufferSize();
-  long bufferOffset = fromOffset + pattern.size();
+  offset_t bufferOffset = fromOffset + pattern.size();
 
   // See the notes in find() for an explanation of this algorithm.
 
@@ -402,12 +402,12 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
   return -1;
 }
 
-void File::insert(const ByteVector &data, unsigned long start, unsigned long replace)
+void File::insert(const ByteVector &data, offset_t start, unsigned long replace)
 {
   d->stream->insert(data, start, replace);
 }
 
-void File::removeBlock(unsigned long start, unsigned long length)
+void File::removeBlock(offset_t start, unsigned long length)
 {
   d->stream->removeBlock(start, length);
 }
@@ -427,12 +427,12 @@ bool File::isValid() const
   return isOpen() && d->valid;
 }
 
-void File::seek(long offset, Position p)
+void File::seek(offset_t offset, Position p)
 {
   d->stream->seek(offset, IOStream::Position(p));
 }
 
-void File::truncate(long length)
+void File::truncate(offset_t length)
 {
   d->stream->truncate(length);
 }
@@ -442,12 +442,12 @@ void File::clear()
   d->stream->clear();
 }
 
-long File::tell() const
+offset_t File::tell() const
 {
   return d->stream->tell();
 }
 
-long File::length()
+offset_t File::length()
 {
   return d->stream->length();
 }
diff --git a/taglib/toolkit/tfile.h b/taglib/toolkit/tfile.h
index bdc4f124..4c87fb36 100644
--- a/taglib/toolkit/tfile.h
+++ b/taglib/toolkit/tfile.h
@@ -180,8 +180,8 @@ namespace TagLib {
      * \note This has the practical limitation that \a pattern can not be longer
      * than the buffer size used by readBlock().  Currently this is 1024 bytes.
      */
-    long find(const ByteVector &pattern,
-              long fromOffset = 0,
+    offset_t find(const ByteVector &pattern,
+              offset_t fromOffset = 0,
               const ByteVector &before = ByteVector());
 
     /*!
@@ -196,8 +196,8 @@ namespace TagLib {
      * \note This has the practical limitation that \a pattern can not be longer
      * than the buffer size used by readBlock().  Currently this is 1024 bytes.
      */
-    long rfind(const ByteVector &pattern,
-               long fromOffset = 0,
+    offset_t rfind(const ByteVector &pattern,
+               offset_t fromOffset = 0,
                const ByteVector &before = ByteVector());
 
     /*!
@@ -207,7 +207,7 @@ namespace TagLib {
      * \note This method is slow since it requires rewriting all of the file
      * after the insertion point.
      */
-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
 
     /*!
      * Removes a block of the file starting a \a start and continuing for
@@ -216,7 +216,7 @@ namespace TagLib {
      * \note This method is slow since it involves rewriting all of the file
      * after the removed portion.
      */
-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
+    void removeBlock(offset_t start = 0, unsigned long length = 0);
 
     /*!
      * Returns true if the file is read only (or if the file can not be opened).
@@ -240,7 +240,7 @@ namespace TagLib {
      *
      * \see Position
      */
-    void seek(long offset, Position p = Beginning);
+    void seek(offset_t offset, Position p = Beginning);
 
     /*!
      * Reset the end-of-file and error flags on the file.
@@ -250,12 +250,12 @@ namespace TagLib {
     /*!
      * Returns the current offset within the file.
      */
-    long tell() const;
+    offset_t tell() const;
 
     /*!
      * Returns the length of the file.
      */
-    long length();
+    offset_t length();
 
     /*!
      * Returns true if \a file can be opened for reading.  If the file does not
@@ -303,7 +303,7 @@ namespace TagLib {
     /*!
      * Truncates the file to a \a length.
      */
-    void truncate(long length);
+    void truncate(offset_t length);
 
     /*!
      * Returns the buffer size that is used for internal buffering.
diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp
index 06aabbd8..73d66663 100644
--- a/taglib/toolkit/tfilestream.cpp
+++ b/taglib/toolkit/tfilestream.cpp
@@ -233,7 +233,7 @@ void FileStream::writeBlock(const ByteVector &data)
   writeFile(d->file, data);
 }
 
-void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
+void FileStream::insert(const ByteVector &data, offset_t start, unsigned long replace)
 {
   if(!isOpen()) {
     debug("FileStream::insert() -- invalid file.");
@@ -267,15 +267,15 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
   // the *difference* in the tag sizes.  We want to avoid overwriting parts
   // that aren't yet in memory, so this is necessary.
 
-  unsigned long bufferLength = bufferSize();
+  size_t bufferLength = bufferSize();
 
   while(data.size() - replace > bufferLength)
     bufferLength += bufferSize();
 
   // Set where to start the reading and writing.
 
-  long readPosition = start + replace;
-  long writePosition = start;
+  offset_t readPosition = start + replace;
+  offset_t writePosition = start;
 
   ByteVector buffer = data;
   ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
@@ -314,7 +314,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
   }
 }
 
-void FileStream::removeBlock(unsigned long start, unsigned long length)
+void FileStream::removeBlock(offset_t start, unsigned long length)
 {
   if(!isOpen()) {
     debug("FileStream::removeBlock() -- invalid file.");
@@ -323,8 +323,8 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
 
   unsigned long bufferLength = bufferSize();
 
-  long readPosition = start + length;
-  long writePosition = start;
+  offset_t readPosition = start + length;
+  offset_t writePosition = start;
 
   ByteVector buffer(static_cast<unsigned int>(bufferLength));
 
@@ -360,7 +360,7 @@ bool FileStream::isOpen() const
   return (d->file != InvalidFileHandle);
 }
 
-void FileStream::seek(long offset, Position p)
+void FileStream::seek(offset_t offset, Position p)
 {
   if(!isOpen()) {
     debug("FileStream::seek() -- invalid file.");
@@ -417,16 +417,15 @@ void FileStream::clear()
 #endif
 }
 
-long FileStream::tell() const
+offset_t FileStream::tell() const
 {
 #ifdef _WIN32
 
   const LARGE_INTEGER zero = {};
   LARGE_INTEGER position;
 
-  if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
-     position.QuadPart <= LONG_MAX) {
-    return static_cast<long>(position.QuadPart);
+  if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT)) {
+    return position.QuadPart;
   }
   else {
     debug("FileStream::tell() -- Failed to get the file pointer.");
@@ -440,7 +439,7 @@ long FileStream::tell() const
 #endif
 }
 
-long FileStream::length()
+offset_t FileStream::length()
 {
   if(!isOpen()) {
     debug("FileStream::length() -- invalid file.");
@@ -461,10 +460,10 @@ long FileStream::length()
 
 #else
 
-  const long curpos = tell();
+  const offset_t curpos = tell();
 
   seek(0, End);
-  const long endpos = tell();
+  const offset_t endpos = tell();
 
   seek(curpos, Beginning);
 
@@ -477,11 +476,11 @@ long FileStream::length()
 // protected members
 ////////////////////////////////////////////////////////////////////////////////
 
-void FileStream::truncate(long length)
+void FileStream::truncate(offset_t length)
 {
 #ifdef _WIN32
 
-  const long currentPos = tell();
+  const offset_t currentPos = tell();
 
   seek(length);
 
diff --git a/taglib/toolkit/tfilestream.h b/taglib/toolkit/tfilestream.h
index aa4d71b3..4f47b26e 100644
--- a/taglib/toolkit/tfilestream.h
+++ b/taglib/toolkit/tfilestream.h
@@ -92,7 +92,7 @@ namespace TagLib {
      * \note This method is slow since it requires rewriting all of the file
      * after the insertion point.
      */
-    void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
+    void insert(const ByteVector &data, offset_t start = 0, unsigned long replace = 0);
 
     /*!
      * Removes a block of the file starting a \a start and continuing for
@@ -101,7 +101,7 @@ namespace TagLib {
      * \note This method is slow since it involves rewriting all of the file
      * after the removed portion.
      */
-    void removeBlock(unsigned long start = 0, unsigned long length = 0);
+    void removeBlock(offset_t start = 0, unsigned long length = 0);
 
     /*!
      * Returns true if the file is read only (or if the file can not be opened).
@@ -120,7 +120,7 @@ namespace TagLib {
      *
      * \see Position
      */
-    void seek(long offset, Position p = Beginning);
+    void seek(offset_t offset, Position p = Beginning);
 
     /*!
      * Reset the end-of-file and error flags on the file.
@@ -130,17 +130,17 @@ namespace TagLib {
     /*!
      * Returns the current offset within the file.
      */
-    long tell() const;
+    offset_t tell() const;
 
     /*!
      * Returns the length of the file.
      */
-    long length();
+    offset_t length();
 
     /*!
      * Truncates the file to a \a length.
      */
-    void truncate(long length);
+    void truncate(offset_t length);
 
   protected:
 
diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h
index 11053164..25417fce 100644
--- a/taglib/toolkit/tiostream.h
+++ b/taglib/toolkit/tiostream.h
@@ -110,7 +110,7 @@ namespace TagLib {
      * after the insertion point.
      */
     virtual void insert(const ByteVector &data,
-                        unsigned long start = 0, unsigned long replace = 0) = 0;
+                        offset_t start = 0, unsigned long replace = 0) = 0;
 
     /*!
      * Removes a block of the file starting a \a start and continuing for
@@ -119,7 +119,7 @@ namespace TagLib {
      * \note This method is slow since it involves rewriting all of the file
      * after the removed portion.
      */
-    virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0;
+    virtual void removeBlock(offset_t start = 0, unsigned long length = 0) = 0;
 
     /*!
      * Returns true if the file is read only (or if the file can not be opened).
@@ -138,7 +138,7 @@ namespace TagLib {
      *
      * \see Position
      */
-    virtual void seek(long offset, Position p = Beginning) = 0;
+    virtual void seek(offset_t offset, Position p = Beginning) = 0;
 
     /*!
      * Reset the end-of-stream and error flags on the stream.
@@ -148,17 +148,17 @@ namespace TagLib {
     /*!
      * Returns the current offset within the stream.
      */
-    virtual long tell() const = 0;
+    virtual offset_t tell() const = 0;
 
     /*!
      * Returns the length of the stream.
      */
-    virtual long length() = 0;
+    virtual offset_t length() = 0;
 
     /*!
      * Truncates the stream to a \a length.
      */
-    virtual void truncate(long length) = 0;
+    virtual void truncate(offset_t length) = 0;
 
   private:
     IOStream(const IOStream &);
diff --git a/taglib/trueaudio/trueaudiofile.cpp b/taglib/trueaudio/trueaudiofile.cpp
index e4de436e..6afd8a5d 100644
--- a/taglib/trueaudio/trueaudiofile.cpp
+++ b/taglib/trueaudio/trueaudiofile.cpp
@@ -63,10 +63,10 @@ public:
   }
 
   const ID3v2::FrameFactory *ID3v2FrameFactory;
-  long ID3v2Location;
+  offset_t ID3v2Location;
   long ID3v2OriginalSize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   TagUnion tag;
 
@@ -290,7 +290,7 @@ void TrueAudio::File::read(bool readProperties)
 
   if(readProperties) {
 
-    long streamLength;
+    offset_t streamLength;
 
     if(d->ID3v1Location >= 0)
       streamLength = d->ID3v1Location;
diff --git a/taglib/trueaudio/trueaudioproperties.cpp b/taglib/trueaudio/trueaudioproperties.cpp
index 0aab2419..3a403848 100644
--- a/taglib/trueaudio/trueaudioproperties.cpp
+++ b/taglib/trueaudio/trueaudioproperties.cpp
@@ -61,7 +61,7 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
+TrueAudio::Properties::Properties(const ByteVector &data, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
@@ -122,7 +122,7 @@ int TrueAudio::Properties::ttaVersion() const
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void TrueAudio::Properties::read(const ByteVector &data, long streamLength)
+void TrueAudio::Properties::read(const ByteVector &data, offset_t streamLength)
 {
   if(data.size() < 4) {
     debug("TrueAudio::Properties::read() -- data is too short.");
diff --git a/taglib/trueaudio/trueaudioproperties.h b/taglib/trueaudio/trueaudioproperties.h
index d25c7a77..fbf1ee75 100644
--- a/taglib/trueaudio/trueaudioproperties.h
+++ b/taglib/trueaudio/trueaudioproperties.h
@@ -54,7 +54,7 @@ namespace TagLib {
        * Create an instance of TrueAudio::Properties with the data read from the
        * ByteVector \a data.
        */
-      Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
+      Properties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Destroys this TrueAudio::Properties instance.
@@ -122,7 +122,7 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void read(const ByteVector &data, long streamLength);
+      void read(const ByteVector &data, offset_t streamLength);
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
diff --git a/taglib/wavpack/wavpackfile.cpp b/taglib/wavpack/wavpackfile.cpp
index 56b99393..af63c491 100644
--- a/taglib/wavpack/wavpackfile.cpp
+++ b/taglib/wavpack/wavpackfile.cpp
@@ -61,10 +61,10 @@ public:
     delete properties;
   }
 
-  long APELocation;
+  offset_t APELocation;
   long APESize;
 
-  long ID3v1Location;
+  offset_t ID3v1Location;
 
   TagUnion tag;
 
@@ -270,7 +270,7 @@ void WavPack::File::read(bool readProperties)
 
   if(readProperties) {
 
-    long streamLength;
+    offset_t streamLength;
 
     if(d->APELocation >= 0)
       streamLength = d->APELocation;
diff --git a/taglib/wavpack/wavpackproperties.cpp b/taglib/wavpack/wavpackproperties.cpp
index 1dd2a054..cc65f2d0 100644
--- a/taglib/wavpack/wavpackproperties.cpp
+++ b/taglib/wavpack/wavpackproperties.cpp
@@ -66,14 +66,14 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-WavPack::Properties::Properties(const ByteVector &, long, ReadStyle style) :
+WavPack::Properties::Properties(const ByteVector &, offset_t, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
   debug("WavPack::Properties::Properties() -- This constructor is no longer used.");
 }
 
-WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) :
+WavPack::Properties::Properties(File *file, offset_t streamLength, ReadStyle style) :
   AudioProperties(style),
   d(new PropertiesPrivate())
 {
@@ -257,9 +257,9 @@ namespace
 
 }  // namespace
 
-void WavPack::Properties::read(File *file, long streamLength)
+void WavPack::Properties::read(File *file, offset_t streamLength)
 {
-  long offset = 0;
+  offset_t offset = 0;
 
   while(true) {
     file->seek(offset);
@@ -339,9 +339,9 @@ void WavPack::Properties::read(File *file, long streamLength)
   }
 }
 
-unsigned int WavPack::Properties::seekFinalIndex(File *file, long streamLength)
+unsigned int WavPack::Properties::seekFinalIndex(File *file, offset_t streamLength)
 {
-  long offset = streamLength;
+  offset_t offset = streamLength;
 
   while (offset >= 32) {
     offset = file->rfind("wvpk", offset - 4);
diff --git a/taglib/wavpack/wavpackproperties.h b/taglib/wavpack/wavpackproperties.h
index e6acdcc3..e169c5e4 100644
--- a/taglib/wavpack/wavpackproperties.h
+++ b/taglib/wavpack/wavpackproperties.h
@@ -58,13 +58,13 @@ namespace TagLib {
        * \deprecated This constructor will be dropped in favor of the one below
        * in a future version.
        */
-      TAGLIB_DEPRECATED Properties(const ByteVector &data, long streamLength,
+      TAGLIB_DEPRECATED Properties(const ByteVector &data, offset_t streamLength,
                                    ReadStyle style = Average);
 
       /*!
        * Create an instance of WavPack::Properties.
        */
-      Properties(File *file, long streamLength, ReadStyle style = Average);
+      Properties(File *file, offset_t streamLength, ReadStyle style = Average);
 
       /*!
        * Destroys this WavPack::Properties instance.
@@ -137,8 +137,8 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void read(File *file, long streamLength);
-      unsigned int seekFinalIndex(File *file, long streamLength);
+      void read(File *file, offset_t streamLength);
+      unsigned int seekFinalIndex(File *file, offset_t streamLength);
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp
index 313e6e77..f921de04 100644
--- a/taglib/xm/xmfile.cpp
+++ b/taglib/xm/xmfile.cpp
@@ -586,7 +586,7 @@ void XM::File::read(bool)
     unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
     READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
 
-    long offset = 0;
+    offset_t offset = 0;
     if(sampleCount > 0) {
       unsigned long sampleHeaderSize = 0;
       sumSampleCount += sampleCount;
