Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Baulig <mabaul@microsoft.com>2019-12-13 21:41:06 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2019-12-13 21:41:06 +0300
commit796b89e2cd892bafa59ab063042a43827c94e976 (patch)
tree48cbc4af6038ff0de320e871111e893172d24e49 /src
parent50db8ee455a3fd71459698d8ab2975e4386d0d8c (diff)
Revert "Cherry-pick dotnet/corefx#37583. (#375)" (#382)
This reverts commit c388c710a7b3d9cfe0ea5d8fe2c1c1ddbeb46ee2. This reverts commit f27f69ac5a5c234c7cb5c6696d0c1119d5a83b92.
Diffstat (limited to 'src')
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs2
-rw-r--r--src/Native/Unix/Common/pal_config.h.in2
-rw-r--r--src/Native/Unix/System.Native/pal_io.c112
-rw-r--r--src/Native/Unix/System.Native/pal_io.h4
-rw-r--r--src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs24
5 files changed, 34 insertions, 110 deletions
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs b/src/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs
index fb97106635..f7035fcead 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs
@@ -11,6 +11,6 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CopyFile", SetLastError = true)]
- internal static extern int CopyFile(SafeFileHandle source, string srcPath, string destPath, int overwrite);
+ internal static extern int CopyFile(SafeFileHandle source, SafeFileHandle destination);
}
}
diff --git a/src/Native/Unix/Common/pal_config.h.in b/src/Native/Unix/Common/pal_config.h.in
index 3665b6a6ee..033e390489 100644
--- a/src/Native/Unix/Common/pal_config.h.in
+++ b/src/Native/Unix/Common/pal_config.h.in
@@ -46,7 +46,7 @@
#cmakedefine01 HAVE_KQUEUE
#cmakedefine01 HAVE_SENDFILE_4
#cmakedefine01 HAVE_SENDFILE_6
-#cmakedefine01 HAVE_CLONEFILE
+#cmakedefine01 HAVE_FCOPYFILE
#cmakedefine01 HAVE_GETNAMEINFO_SIGNED_FLAGS
#cmakedefine01 HAVE_GETPEEREID
#cmakedefine01 HAVE_SUPPORT_FOR_DUAL_MODE_IPV4_PACKET_INFO
diff --git a/src/Native/Unix/System.Native/pal_io.c b/src/Native/Unix/System.Native/pal_io.c
index 1406ee72c1..ddd56b91c9 100644
--- a/src/Native/Unix/System.Native/pal_io.c
+++ b/src/Native/Unix/System.Native/pal_io.c
@@ -28,11 +28,9 @@
#include <termios.h>
#include <unistd.h>
#include <limits.h>
-#if HAVE_CLONEFILE
-#include <sys/attr.h>
-#include <sys/clonefile.h>
-#endif
-#if HAVE_SENDFILE_4
+#if HAVE_FCOPYFILE
+#include <copyfile.h>
+#elif HAVE_SENDFILE_4
#include <sys/sendfile.h>
#endif
#if HAVE_INOTIFY
@@ -1195,6 +1193,7 @@ int32_t SystemNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize)
return (int32_t)count;
}
+#if !HAVE_FCOPYFILE
// Read all data from inFd and write it to outFd
static int32_t CopyFile_ReadWrite(int inFd, int outFd)
{
@@ -1247,15 +1246,25 @@ static int32_t CopyFile_ReadWrite(int inFd, int outFd)
free(buffer);
return 0;
}
+#endif // !HAVE_FCOPYFILE
-int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char* destPath, int32_t overwrite)
+int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
{
int inFd = ToFileDescriptor(sourceFd);
- int outFd;
+ int outFd = ToFileDescriptor(destinationFd);
+
+#if HAVE_FCOPYFILE
+ // If fcopyfile is available (OS X), try to use it, as the whole copy
+ // can be performed in the kernel, without lots of unnecessary copying.
+ // Copy data and metadata.
+ return fcopyfile(inFd, outFd, NULL, COPYFILE_ALL) == 0 ? 0 : -1;
+#else
+ // Get the stats on the source file.
int ret;
- int tmpErrno;
- int openFlags;
struct stat_ sourceStat;
+ bool copied = false;
+
+ // First, stat the source file.
while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
if (ret != 0)
{
@@ -1275,74 +1284,9 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char
}
#endif
- struct stat_ destStat;
- while ((ret = stat_(destPath, &destStat)) < 0 && errno == EINTR);
- if (ret == 0)
- {
- if (!overwrite)
- {
- errno = EEXIST;
- return -1;
- }
-
- if (sourceStat.st_dev == destStat.st_dev && sourceStat.st_ino == destStat.st_ino)
- {
- // Attempt to copy file over itself. Fail with the same error code as
- // open would.
- errno = EBUSY;
- return -1;
- }
-
-#if HAVE_CLONEFILE
- // For clonefile we need to unlink the destination file first but we need to
- // check permission first to ensure we don't try to unlink read-only file.
- if (access(destPath, W_OK) != 0)
- {
- return -1;
- }
-
- ret = unlink(destPath);
- if (ret != 0)
- {
- return ret;
- }
-#endif
- }
-
-#if HAVE_CLONEFILE
- while ((ret = clonefile(srcPath, destPath, 0)) < 0 && errno == EINTR);
- // EEXIST can happen due to race condition between the stat/unlink above
- // and the clonefile here. The file could be (re-)created from another
- // thread or process before we have a chance to call clonefile. Handle
- // it by falling back to the slow path.
- if (ret == 0 || (errno != ENOTSUP && errno != EXDEV && errno != EEXIST))
- {
- return ret;
- }
-#else
- // Unused variable
- (void)srcPath;
-#endif
-
- openFlags = O_WRONLY | O_TRUNC | O_CREAT | (overwrite ? 0 : O_EXCL);
-#if HAVE_O_CLOEXEC
- openFlags |= O_CLOEXEC;
-#endif
- while ((outFd = open(destPath, openFlags, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
- if (outFd < 0)
- {
- return -1;
- }
-#if !HAVE_O_CLOEXEC
- fcntl(outFd, F_SETFD, FD_CLOEXEC);
-#endif
-
- // Get the stats on the source file.
- bool copied = false;
-
+#if HAVE_SENDFILE_4
// If sendfile is available (Linux), try to use it, as the whole copy
// can be performed in the kernel, without lots of unnecessary copying.
-#if HAVE_SENDFILE_4
// On 32-bit, if you use 64-bit offsets, the last argument of `sendfile' will be a
// `size_t' a 32-bit integer while the `st_size' field of the stat structure will be off64_t.
@@ -1358,9 +1302,6 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char
{
if (errno != EINVAL && errno != ENOSYS)
{
- tmpErrno = errno;
- close(outFd);
- errno = tmpErrno;
return -1;
}
else
@@ -1386,9 +1327,6 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char
// Manually read all data from the source and write it to the destination.
if (!copied && CopyFile_ReadWrite(inFd, outFd) != 0)
{
- tmpErrno = errno;
- close(outFd);
- errno = tmpErrno;
return -1;
}
@@ -1413,10 +1351,16 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char
while ((ret = futimes(outFd, origTimes)) < 0 && errno == EINTR);
#endif
- tmpErrno = errno;
- close(outFd);
- errno = tmpErrno;
+#if !TARGET_ANDROID
+ // On Android, the copy should still succeed even if copying the file times didn't.
+ if (ret != 0)
+ {
+ return -1;
+ }
+#endif
+
return 0;
+#endif // HAVE_FCOPYFILE
}
intptr_t SystemNative_INotifyInit(void)
diff --git a/src/Native/Unix/System.Native/pal_io.h b/src/Native/Unix/System.Native/pal_io.h
index 125b006d44..f13cdc6606 100644
--- a/src/Native/Unix/System.Native/pal_io.h
+++ b/src/Native/Unix/System.Native/pal_io.h
@@ -705,11 +705,11 @@ DLLEXPORT void SystemNative_Sync(void);
DLLEXPORT int32_t SystemNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize);
/**
- * Copies all data from the source file descriptor/path to the destination file path.
+ * Copies all data from the source file descriptor to the destination file descriptor.
*
* Returns 0 on success; otherwise, returns -1 and sets errno.
*/
-DLLEXPORT int32_t SystemNative_CopyFile(intptr_t sourceFd, const char* srcPath, const char* destPath, int32_t overwrite);
+DLLEXPORT int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd);
/**
* Initializes a new inotify instance and returns a file
diff --git a/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs b/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
index 6a4b97ba67..b2007ca32d 100644
--- a/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
+++ b/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
@@ -52,29 +52,9 @@ namespace System.IO
// Copy the contents of the file from the source to the destination, creating the destination in the process
using (var src = new FileStream(sourceFullPath, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, FileOptions.None))
+ using (var dst = new FileStream(destFullPath, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, DefaultBufferSize, FileOptions.None))
{
- int result = Interop.Sys.CopyFile(src.SafeFileHandle, sourceFullPath, destFullPath, overwrite ? 1 : 0);
-
- if (result < 0)
- {
- Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
-
- // If we fail to open the file due to a path not existing, we need to know whether to blame
- // the file itself or its directory. If we're creating the file, then we blame the directory,
- // otherwise we blame the file.
- //
- // When opening, we need to align with Windows, which considers a missing path to be
- // FileNotFound only if the containing directory exists.
-
- bool isDirectory = (error.Error == Interop.Error.ENOENT) &&
- (overwrite || !DirectoryExists(Path.GetDirectoryName(PathInternal.TrimEndingDirectorySeparator(destFullPath))));
-
- Interop.CheckIo(
- error.Error,
- destFullPath,
- isDirectory,
- errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e);
- }
+ Interop.CheckIo(Interop.Sys.CopyFile(src.SafeFileHandle, dst.SafeFileHandle));
}
}