VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/RTFileCopyPartEx-linux.cpp@ 82968

Last change on this file since 82968 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: RTFileCopyPartEx-linux.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * IPRT - RTFileCopyPartEx, linux specific implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/file.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37
38#include <errno.h>
39#include <unistd.h>
40#include <sys/syscall.h>
41
42#ifndef __NR_copy_file_range
43# if defined(RT_ARCH_X86)
44# define __NR_copy_file_range 377
45# elif defined(RT_ARCH_AMD64)
46# define __NR_copy_file_range 326
47# endif
48#endif
49
50
51#ifndef __NR_copy_file_range
52# include "../../generic/RTFileCopyPartEx-generic.cpp"
53#else /* __NR_copy_file_range - whole file */
54/* Include the generic code as a fallback since copy_file_range is rather new . */
55# define IPRT_FALLBACK_VERSION
56# include "../../generic/RTFileCopyPartEx-generic.cpp"
57# undef IPRT_FALLBACK_VERSION
58
59
60/*********************************************************************************************************************************
61* Global Variables *
62*********************************************************************************************************************************/
63static int32_t volatile g_fCopyFileRangeSupported = -1;
64
65
66DECLINLINE(loff_t)
67MyCopyFileRangeSysCall(int fdIn, loff_t *poffIn, int fdOut, loff_t *poffOut, size_t cbChunk, unsigned int fFlags)
68{
69 return syscall(__NR_copy_file_range, fdIn, poffIn, fdOut, poffOut, cbChunk, fFlags);
70}
71
72
73DECL_NO_INLINE(static, bool) HasCopyFileRangeSyscallSlow(void)
74{
75 errno = 0;
76 MyCopyFileRangeSysCall(-1, NULL, -1, NULL, 4096, 0);
77 if (errno != ENOSYS)
78 {
79 ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 1);
80 return true;
81 }
82 ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 0);
83 return false;
84}
85
86DECLINLINE(bool) HasCopyFileRangeSyscall(void)
87{
88 int32_t i = ASMAtomicUoReadS32(&g_fCopyFileRangeSupported);
89 if (i != -1)
90 return i == 1;
91 return HasCopyFileRangeSyscallSlow();
92}
93
94
95
96RTDECL(int) RTFileCopyPartPrep(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy)
97{
98 if (HasCopyFileRangeSyscall())
99 {
100 pBufState->iAllocType = -42;
101 pBufState->pbBuf = NULL;
102 pBufState->cbBuf = 0;
103 pBufState->uMagic = RTFILECOPYPARTBUFSTATE_MAGIC;
104 return VINF_SUCCESS;
105 }
106 return rtFileCopyPartPrepFallback(pBufState, cbToCopy);
107}
108
109
110RTDECL(void) RTFileCopyPartCleanup(PRTFILECOPYPARTBUFSTATE pBufState)
111{
112 return rtFileCopyPartCleanupFallback(pBufState);
113}
114
115
116RTDECL(int) RTFileCopyPartEx(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
117 uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied)
118{
119 /*
120 * Validate input.
121 */
122 if (pcbCopied)
123 *pcbCopied = 0;
124 AssertReturn(pBufState->uMagic == RTFILECOPYPARTBUFSTATE_MAGIC, VERR_INVALID_FLAGS);
125 if (pBufState->iAllocType == -42)
126 { /* more and more likley as time goes */ }
127 else
128 return rtFileCopyPartExFallback(hFileSrc, offSrc, hFileDst, offDst, cbToCopy, fFlags, pBufState, pcbCopied);
129 AssertReturn(offSrc >= 0, VERR_NEGATIVE_SEEK);
130 AssertReturn(offDst >= 0, VERR_NEGATIVE_SEEK);
131 AssertReturn(!fFlags, VERR_INVALID_FLAGS);
132
133 /*
134 * If nothing to copy, return right away.
135 */
136 if (!cbToCopy)
137 return VINF_SUCCESS;
138
139 /*
140 * Do the copying.
141 */
142 uint64_t cbCopied = 0;
143 int rc = VINF_SUCCESS;
144 do
145 {
146 size_t cbThisCopy = (size_t)RT_MIN(cbToCopy - cbCopied, _1G);
147 loff_t offThisDst = offSrc + cbCopied;
148 loff_t offThisSrc = offDst + cbCopied;
149 ssize_t cbActual = MyCopyFileRangeSysCall((int)RTFileToNative(hFileSrc), &offThisSrc,
150 (int)RTFileToNative(hFileDst), &offThisDst,
151 cbThisCopy, 0);
152 if (cbActual < 0)
153 {
154 rc = errno;
155 Assert(rc != 0);
156 rc = rc != 0 ? RTErrConvertFromErrno(rc) : VERR_READ_ERROR;
157 break;
158 }
159 Assert(offThisSrc == offSrc + (int64_t)cbCopied + cbActual);
160 Assert(offThisDst == offDst + (int64_t)cbCopied + cbActual);
161
162 if (cbActual == 0)
163 {
164 if (!pcbCopied)
165 rc = VERR_EOF;
166 break;
167 }
168
169 cbCopied += cbActual;
170 } while (cbCopied < cbToCopy);
171
172 if (pcbCopied)
173 *pcbCopied = cbCopied;
174
175 return rc;
176}
177
178#endif /* __NR_copy_file_range */
179
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette