diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 42250b629dcb19c49b95854c3fdddbe426998a5b..a1266902406e77bfc9363d9593f02970866e9c76 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -73,6 +73,17 @@ QT_BEGIN_NAMESPACE
 #  endif
 #endif
 
+#ifdef Q_OS_WIN
+// on Windows, read() and write() use int and unsigned int
+typedef int SignedIOType;
+typedef unsigned int UnsignedIOType;
+#else
+typedef ssize_t SignedIOType;
+typedef size_t UnsignedIOType;
+Q_STATIC_ASSERT_X(sizeof(SignedIOType) == sizeof(UnsignedIOType),
+                  "Unsupported: read/write return a type with different size as the len parameter");
+#endif
+
 /*! \class QFSFileEngine
     \inmodule QtCore
     \brief The QFSFileEngine class implements Qt's default file engine.
@@ -605,13 +616,16 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
     } else if (fd != -1) {
         // Unbuffered stdio mode.
 
-#ifdef Q_OS_WIN
-        int result;
-#else
-        ssize_t result;
-#endif
+        SignedIOType result;
         do {
-            result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
+            // calculate the chunk size
+            // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
+            // we limit to the size of the signed type, otherwise we could get a negative number as a result
+            quint64 wantedBytes = quint64(len) - quint64(readBytes);
+            UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
+            if (chunkSize > wantedBytes)
+                chunkSize = wantedBytes;
+            result = QT_READ(fd, data + readBytes, chunkSize);
         } while (result > 0 && (readBytes += result) < len);
 
         eof = !(result == -1);
@@ -722,13 +736,16 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
     } else if (fd != -1) {
         // Unbuffered stdio mode.
 
-#ifdef Q_OS_WIN
-        int result;
-#else
-        ssize_t result;
-#endif
+        SignedIOType result;
         do {
-            result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
+            // calculate the chunk size
+            // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
+            // we limit to the size of the signed type, otherwise we could get a negative number as a result
+            quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
+            UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
+            if (chunkSize > wantedBytes)
+                chunkSize = wantedBytes;
+            result = QT_WRITE(fd, data + writtenBytes, chunkSize);
         } while (result > 0 && (writtenBytes += result) < len);
     }
 
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 89209e6118f483721e6a3fcc36df97342ddc8894..0709a93bad94dd0a4e2e966c230a34f77d792693 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -786,7 +786,7 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
     bool moreToRead = true;
     do {
         // Try reading from the buffer.
-        int lastReadChunkSize = d->buffer.read(data, maxSize);
+        qint64 lastReadChunkSize = d->buffer.read(data, maxSize);
         if (lastReadChunkSize > 0) {
             *d->pPos += lastReadChunkSize;
             readSoFar += lastReadChunkSize;
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 10d92a896d76bb18c2795ab8f8b88aa4130d4d12..d764cb0fbb05c2972b93da6a97dbd8d8da7962ec 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -98,19 +98,19 @@ public:
         first++;
         return ch;
     }
-    int read(char* target, qint64 size) {
-        int r = qMin(size, len);
+    qint64 read(char* target, qint64 size) {
+        qint64 r = qMin(size, len);
         memcpy(target, first, r);
         len -= r;
         first += r;
         return r;
     }
-    int peek(char* target, qint64 size) {
-        int r = qMin(size, len);
+    qint64 peek(char* target, qint64 size) {
+        qint64 r = qMin(size, len);
         memcpy(target, first, r);
         return r;
     }
-    char* reserve(int size) {
+    char* reserve(qint64 size) {
         makeSpace(size + len, freeSpaceAtEnd);
         char* writePtr = first + len;
         len += size;
@@ -128,16 +128,16 @@ public:
         clear();
         return retVal;
     }
-    int readLine(char* target, qint64 size) {
-        int r = qMin(size, len);
+    qint64 readLine(char* target, qint64 size) {
+        qint64 r = qMin(size, len);
         char* eol = static_cast<char*>(memchr(first, '\n', r));
         if (eol)
             r = 1+(eol-first);
         memcpy(target, first, r);
         len -= r;
         first += r;
-        return int(r);
-        }
+        return r;
+    }
     bool canReadLine() const {
         return memchr(first, '\n', len);
     }