Index: trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- trunk/src/VBox/Runtime/Makefile.kmk	(revision 77831)
+++ trunk/src/VBox/Runtime/Makefile.kmk	(revision 77832)
@@ -670,5 +670,4 @@
 	generic/RTFileCopyByHandlesEx-generic.cpp \
 	generic/RTFileCopyPart-generic.cpp \
-	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileQuerySize-generic.cpp \
 	generic/RTFileReadAll-generic.cpp \
@@ -822,4 +821,5 @@
 	generic/fileio-sg-generic.cpp \
 	generic/fileio-sg-at-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileExists-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -942,4 +942,5 @@
 	r3/linux/time-linux.cpp \
 	r3/linux/thread-affinity-linux.cpp \
+	r3/linux/RTFileCopyPartEx-linux.cpp \
 	r3/linux/RTFileSetAllocationSize-linux.cpp \
 	r3/linux/RTProcIsRunningByName-linux.cpp \
@@ -1018,4 +1019,5 @@
 	generic/fileio-sg-generic.cpp \
 	generic/fileio-sg-at-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -1099,4 +1101,5 @@
 	generic/RTDirQueryInfo-generic.cpp \
 	generic/RTDirSetTimes-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -1184,4 +1187,5 @@
 	generic/RTDirQueryInfo-generic.cpp \
 	generic/RTDirSetTimes-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -1267,4 +1271,5 @@
 	generic/RTDirQueryInfo-generic.cpp \
 	generic/RTDirSetTimes-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
@@ -1348,4 +1353,5 @@
 	generic/RTDirQueryInfo-generic.cpp \
 	generic/RTDirSetTimes-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
@@ -1443,4 +1449,5 @@
 	generic/fileio-sg-generic.cpp \
 	generic/fileio-sg-at-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -1794,5 +1801,4 @@
 	generic/RTFileCopyEx-generic.cpp \
 	generic/RTFileCopyByHandlesEx-generic.cpp \
-	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileQuerySize-generic.cpp \
 	generic/RTFileReadAll-generic.cpp \
@@ -1835,4 +1841,5 @@
 RuntimeBldProg_SOURCES.darwin = $(filter-out \
 	generic/cdrom-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
@@ -1874,4 +1881,5 @@
 	generic/RTDirExists-generic.cpp \
 	generic/RTDirSetTimes-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileExists-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
@@ -1942,4 +1950,5 @@
 	generic/RTDirSetTimes-generic.cpp \
 	generic/fileio-at-generic.cpp \
+	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
Index: trunk/src/VBox/Runtime/generic/RTFileCopyPartEx-generic.cpp
===================================================================
--- trunk/src/VBox/Runtime/generic/RTFileCopyPartEx-generic.cpp	(revision 77831)
+++ trunk/src/VBox/Runtime/generic/RTFileCopyPartEx-generic.cpp	(revision 77832)
@@ -38,5 +38,9 @@
 
 
+#ifndef IPRT_FALLBACK_VERSION
 RTDECL(int) RTFileCopyPartPrep(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy)
+#else
+static int rtFileCopyPartPrepFallback(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy)
+#endif
 {
     /*
@@ -71,5 +75,9 @@
 
 
+#ifndef IPRT_FALLBACK_VERSION
 RTDECL(void) RTFileCopyPartCleanup(PRTFILECOPYPARTBUFSTATE pBufState)
+#else
+static void rtFileCopyPartCleanupFallback(PRTFILECOPYPARTBUFSTATE pBufState)
+#endif
 {
     AssertReturnVoid(pBufState->uMagic == RTFILECOPYPARTBUFSTATE_MAGIC);
@@ -84,6 +92,11 @@
 
 
+#ifndef IPRT_FALLBACK_VERSION
 RTDECL(int) RTFileCopyPartEx(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
                              uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied)
+#else
+static int rtFileCopyPartExFallback(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
+                                    uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied)
+#endif
 {
     /*
@@ -117,5 +130,5 @@
     do
     {
-        size_t cbThisCopy = (size_t)RT_MIN(cbToCopy, pBufState->cbBuf);
+        size_t cbThisCopy = (size_t)RT_MIN(cbToCopy - cbCopied, pBufState->cbBuf);
         size_t cbActual   = 0;
         rc = RTFileReadAt(hFileSrc, offSrc + cbCopied, pBufState->pbBuf, cbThisCopy, &cbActual);
@@ -141,4 +154,3 @@
     return rc;
 }
-RT_EXPORT_SYMBOL(RTFileCopyPartEx);
 
Index: trunk/src/VBox/Runtime/r3/linux/RTFileCopyPartEx-linux.cpp
===================================================================
--- trunk/src/VBox/Runtime/r3/linux/RTFileCopyPartEx-linux.cpp	(revision 77832)
+++ trunk/src/VBox/Runtime/r3/linux/RTFileCopyPartEx-linux.cpp	(revision 77832)
@@ -0,0 +1,167 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileCopyPartEx, generic implementation.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/file.h>
+#include "internal/iprt.h"
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* Include the generic code as a fallback since copy_file_range is rather new . */
+#define IPRT_FALLBACK_VERSION
+#include "../../generic/RTFileCopyPartEx-generic.cpp"
+#undef  IPRT_FALLBACK_VERSION
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+static int32_t volatile g_fCopyFileRangeSupported = -1;
+
+
+DECLINLINE(loff_t)
+MyCopyFileRangeSysCall(int fdIn, loff_t *poffIn, int fdOut, loff_t *poffOut, size_t cbChunk, unsigned int fFlags)
+{
+    return syscall(__NR_copy_file_range, fdIn, poffIn, fdOut, poffOut, cbChunk, fFlags);
+}
+
+
+DECL_NO_INLINE(static, bool) HasCopyFileRangeSyscallSlow(void)
+{
+    errno = 0;
+    MyCopyFileRangeSysCall(-1, NULL, -1, NULL, 4096, 0);
+    if (errno != ENOSYS)
+    {
+        ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 1);
+        return true;
+    }
+    ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 0);
+    return false;
+}
+
+DECLINLINE(bool) HasCopyFileRangeSyscall(void)
+{
+    int32_t i = ASMAtomicUoReadS32(&g_fCopyFileRangeSupported);
+    if (i != -1)
+        return i == 1;
+    return HasCopyFileRangeSyscallSlow();
+}
+
+
+
+RTDECL(int) RTFileCopyPartPrep(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy)
+{
+    if (HasCopyFileRangeSyscall())
+    {
+        pBufState->iAllocType = -42;
+        pBufState->pbBuf      = NULL;
+        pBufState->cbBuf      = 0;
+        pBufState->uMagic     = RTFILECOPYPARTBUFSTATE_MAGIC;
+        return VINF_SUCCESS;
+    }
+    return rtFileCopyPartPrepFallback(pBufState, cbToCopy);
+}
+
+
+RTDECL(void) RTFileCopyPartCleanup(PRTFILECOPYPARTBUFSTATE pBufState)
+{
+    return rtFileCopyPartCleanupFallback(pBufState);
+}
+
+
+RTDECL(int) RTFileCopyPartEx(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
+                             uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied)
+{
+    /*
+     * Validate input.
+     */
+    if (pcbCopied)
+        *pcbCopied = 0;
+    AssertReturn(pBufState->uMagic == RTFILECOPYPARTBUFSTATE_MAGIC, VERR_INVALID_FLAGS);
+    if (pBufState->iAllocType == -42)
+    { /* more and more likley as time goes */ }
+    else
+        return rtFileCopyPartExFallback(hFileSrc, offSrc, hFileDst, offDst, cbToCopy, fFlags, pBufState, pcbCopied);
+    AssertReturn(offSrc >= 0, VERR_NEGATIVE_SEEK);
+    AssertReturn(offDst >= 0, VERR_NEGATIVE_SEEK);
+    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
+
+    /*
+     * If nothing to copy, return right away.
+     */
+    if (!cbToCopy)
+        return VINF_SUCCESS;
+
+    /*
+     * Do the copying.
+     */
+    uint64_t cbCopied = 0;
+    int      rc       = VINF_SUCCESS;
+    do
+    {
+        size_t  cbThisCopy = (size_t)RT_MIN(cbToCopy - cbCopied, _1G);
+        loff_t  offThisDst = offSrc + cbCopied;
+        loff_t  offThisSrc = offDst + cbCopied;
+        ssize_t cbActual   = MyCopyFileRangeSysCall((int)RTFileToNative(hFileSrc), &offThisSrc,
+                                                    (int)RTFileToNative(hFileDst), &offThisDst,
+                                                    cbThisCopy, 0);
+        if (cbActual < 0)
+        {
+            rc = errno;
+            Assert(rc != 0);
+            rc = rc != 0 ? RTErrConvertFromErrno(rc) : VERR_READ_ERROR;
+            break;
+        }
+        Assert(offThisSrc == offSrc + (int64_t)cbCopied + cbActual);
+        Assert(offThisDst == offDst + (int64_t)cbCopied + cbActual);
+
+        if (cbActual == 0)
+        {
+            if (!pcbCopied)
+                rc = VERR_EOF;
+            break;
+        }
+
+        cbCopied += cbActual;
+    } while (cbCopied < cbToCopy);
+
+    if (pcbCopied)
+        *pcbCopied = cbCopied;
+
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTFileCopyPartEx);
+
+
