mirror of
https://github.com/reactos/CMake.git
synced 2025-02-02 01:55:03 +00:00
Merge branch 'upstream-KWSys' into update-kwsys
* upstream-KWSys: KWSys 2018-12-12 (abb8c680)
This commit is contained in:
commit
b29d96701b
@ -82,6 +82,10 @@
|
||||
# include <signal.h> /* sigprocmask */
|
||||
#endif
|
||||
|
||||
#ifdef __linux
|
||||
# include <linux/fs.h>
|
||||
#endif
|
||||
|
||||
// Windows API.
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
@ -2157,6 +2161,120 @@ bool SystemTools::FilesDiffer(const std::string& source,
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blockwise copy source to destination file
|
||||
*/
|
||||
static bool CopyFileContentBlockwise(const std::string& source,
|
||||
const std::string& destination)
|
||||
{
|
||||
// Open files
|
||||
#if defined(_WIN32)
|
||||
kwsys::ifstream fin(
|
||||
Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
|
||||
std::ios::in | std::ios::binary);
|
||||
#else
|
||||
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
|
||||
#endif
|
||||
if (!fin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try and remove the destination file so that read only destination files
|
||||
// can be written to.
|
||||
// If the remove fails continue so that files in read only directories
|
||||
// that do not allow file removal can be modified.
|
||||
SystemTools::RemoveFile(destination);
|
||||
|
||||
#if defined(_WIN32)
|
||||
kwsys::ofstream fout(
|
||||
Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(),
|
||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
#else
|
||||
kwsys::ofstream fout(destination.c_str(),
|
||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
#endif
|
||||
if (!fout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This copy loop is very sensitive on certain platforms with
|
||||
// slightly broken stream libraries (like HPUX). Normally, it is
|
||||
// incorrect to not check the error condition on the fin.read()
|
||||
// before using the data, but the fin.gcount() will be zero if an
|
||||
// error occurred. Therefore, the loop should be safe everywhere.
|
||||
while (fin) {
|
||||
const int bufferSize = 4096;
|
||||
char buffer[bufferSize];
|
||||
|
||||
fin.read(buffer, bufferSize);
|
||||
if (fin.gcount()) {
|
||||
fout.write(buffer, fin.gcount());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the operating system has finished writing the file
|
||||
// before closing it. This will ensure the file is finished before
|
||||
// the check below.
|
||||
fout.flush();
|
||||
|
||||
fin.close();
|
||||
fout.close();
|
||||
|
||||
if (!fout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the source file to the destination file
|
||||
*
|
||||
* If available, the Linux FICLONE ioctl is used to create a check
|
||||
* copy-on-write clone of the source file.
|
||||
*
|
||||
* The method returns false for the following cases:
|
||||
* - The code has not been compiled on Linux or the ioctl was unknown
|
||||
* - The source and destination is on different file systems
|
||||
* - The underlying filesystem does not support file cloning
|
||||
* - An unspecified error occurred
|
||||
*/
|
||||
static bool CloneFileContent(const std::string& source,
|
||||
const std::string& destination)
|
||||
{
|
||||
#if defined(__linux) && defined(FICLONE)
|
||||
int in = open(source.c_str(), O_RDONLY);
|
||||
if (in < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SystemTools::RemoveFile(destination);
|
||||
|
||||
int out =
|
||||
open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (out < 0) {
|
||||
close(in);
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = ioctl(out, FICLONE, in);
|
||||
close(in);
|
||||
close(out);
|
||||
|
||||
if (result < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
(void)source;
|
||||
(void)destination;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file named by "source" to the file named by "destination".
|
||||
*/
|
||||
@ -2174,9 +2292,6 @@ bool SystemTools::CopyFileAlways(const std::string& source,
|
||||
if (SystemTools::FileIsDirectory(source)) {
|
||||
SystemTools::MakeDirectory(destination);
|
||||
} else {
|
||||
const int bufferSize = 4096;
|
||||
char buffer[bufferSize];
|
||||
|
||||
// If destination is a directory, try to create a file with the same
|
||||
// name as the source in that directory.
|
||||
|
||||
@ -2195,62 +2310,12 @@ bool SystemTools::CopyFileAlways(const std::string& source,
|
||||
|
||||
SystemTools::MakeDirectory(destination_dir);
|
||||
|
||||
// Open files
|
||||
#if defined(_WIN32)
|
||||
kwsys::ifstream fin(
|
||||
Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
|
||||
std::ios::in | std::ios::binary);
|
||||
#else
|
||||
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
|
||||
#endif
|
||||
if (!fin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try and remove the destination file so that read only destination files
|
||||
// can be written to.
|
||||
// If the remove fails continue so that files in read only directories
|
||||
// that do not allow file removal can be modified.
|
||||
SystemTools::RemoveFile(real_destination);
|
||||
|
||||
#if defined(_WIN32)
|
||||
kwsys::ofstream fout(
|
||||
Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(real_destination))
|
||||
.c_str(),
|
||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
#else
|
||||
kwsys::ofstream fout(real_destination.c_str(),
|
||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
#endif
|
||||
if (!fout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This copy loop is very sensitive on certain platforms with
|
||||
// slightly broken stream libraries (like HPUX). Normally, it is
|
||||
// incorrect to not check the error condition on the fin.read()
|
||||
// before using the data, but the fin.gcount() will be zero if an
|
||||
// error occurred. Therefore, the loop should be safe everywhere.
|
||||
while (fin) {
|
||||
fin.read(buffer, bufferSize);
|
||||
if (fin.gcount()) {
|
||||
fout.write(buffer, fin.gcount());
|
||||
} else {
|
||||
break;
|
||||
if (!CloneFileContent(source, real_destination)) {
|
||||
// if cloning did not succeed, fall back to blockwise copy
|
||||
if (!CopyFileContentBlockwise(source, real_destination)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the operating system has finished writing the file
|
||||
// before closing it. This will ensure the file is finished before
|
||||
// the check below.
|
||||
fout.flush();
|
||||
|
||||
fin.close();
|
||||
fout.close();
|
||||
|
||||
if (!fout) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (perms) {
|
||||
if (!SystemTools::SetPermissions(real_destination, perm)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user