Commit 0664553b authored by Brad King's avatar Brad King
Browse files

SystemTools: Return Status from copy operations

parent 6aec6af9
...@@ -2129,8 +2129,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir) ...@@ -2129,8 +2129,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir)
return new_destination + '/' + SystemTools::GetFilenameName(source); return new_destination + '/' + SystemTools::GetFilenameName(source);
} }
bool SystemTools::CopyFileIfDifferent(const std::string& source, Status SystemTools::CopyFileIfDifferent(std::string const& source,
const std::string& destination) std::string const& destination)
{ {
// special check for a destination that is a directory // special check for a destination that is a directory
// FilesDiffer does not handle file to directory compare // FilesDiffer does not handle file to directory compare
...@@ -2147,7 +2147,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source, ...@@ -2147,7 +2147,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source,
} }
} }
// at this point the files must be the same so return true // at this point the files must be the same so return true
return true; return Status::Success();
} }
#define KWSYS_ST_BUFFER 4096 #define KWSYS_ST_BUFFER 4096
...@@ -2273,13 +2273,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, ...@@ -2273,13 +2273,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
return false; return false;
} }
bool SystemTools::CopyFileContentBlockwise(const std::string& source, Status SystemTools::CopyFileContentBlockwise(std::string const& source,
const std::string& destination) std::string const& destination)
{ {
// Open files // Open files
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
if (!fin) { if (!fin) {
return false; return Status::POSIX_errno();
} }
// try and remove the destination file so that read only destination files // try and remove the destination file so that read only destination files
...@@ -2291,7 +2291,7 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, ...@@ -2291,7 +2291,7 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source,
kwsys::ofstream fout(destination.c_str(), kwsys::ofstream fout(destination.c_str(),
std::ios::out | std::ios::trunc | std::ios::binary); std::ios::out | std::ios::trunc | std::ios::binary);
if (!fout) { if (!fout) {
return false; return Status::POSIX_errno();
} }
// This copy loop is very sensitive on certain platforms with // This copy loop is very sensitive on certain platforms with
...@@ -2320,10 +2320,10 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, ...@@ -2320,10 +2320,10 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source,
fout.close(); fout.close();
if (!fout) { if (!fout) {
return false; return Status::POSIX_errno();
} }
return true; return Status::Success();
} }
/** /**
...@@ -2338,13 +2338,13 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, ...@@ -2338,13 +2338,13 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source,
* - The underlying filesystem does not support file cloning * - The underlying filesystem does not support file cloning
* - An unspecified error occurred * - An unspecified error occurred
*/ */
bool SystemTools::CloneFileContent(const std::string& source, Status SystemTools::CloneFileContent(std::string const& source,
const std::string& destination) std::string const& destination)
{ {
#if defined(__linux) && defined(FICLONE) #if defined(__linux) && defined(FICLONE)
int in = open(source.c_str(), O_RDONLY); int in = open(source.c_str(), O_RDONLY);
if (in < 0) { if (in < 0) {
return false; return Status::POSIX_errno();
} }
SystemTools::RemoveFile(destination); SystemTools::RemoveFile(destination);
...@@ -2352,38 +2352,42 @@ bool SystemTools::CloneFileContent(const std::string& source, ...@@ -2352,38 +2352,42 @@ bool SystemTools::CloneFileContent(const std::string& source,
int out = int out =
open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (out < 0) { if (out < 0) {
Status status = Status::POSIX_errno();
close(in); close(in);
return false; return status;
} }
int result = ioctl(out, FICLONE, in); Status status = Status::Success();
if (ioctl(out, FICLONE, in) < 0) {
status = Status::POSIX_errno();
}
close(in); close(in);
close(out); close(out);
if (result < 0) { return status;
return false;
}
return true;
#else #else
(void)source; (void)source;
(void)destination; (void)destination;
return false; return Status::POSIX(ENOSYS);
#endif #endif
} }
/** /**
* Copy a file named by "source" to the file named by "destination". * Copy a file named by "source" to the file named by "destination".
*/ */
bool SystemTools::CopyFileAlways(const std::string& source, Status SystemTools::CopyFileAlways(std::string const& source,
const std::string& destination) std::string const& destination)
{ {
Status status;
mode_t perm = 0; mode_t perm = 0;
Status perms = SystemTools::GetPermissions(source, perm); Status perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination; std::string real_destination = destination;
if (SystemTools::FileIsDirectory(source)) { if (SystemTools::FileIsDirectory(source)) {
SystemTools::MakeDirectory(destination); status = SystemTools::MakeDirectory(destination);
if (!status) {
return status;
}
} else { } else {
// If destination is a directory, try to create a file with the same // If destination is a directory, try to create a file with the same
// name as the source in that directory. // name as the source in that directory.
...@@ -2400,30 +2404,34 @@ bool SystemTools::CopyFileAlways(const std::string& source, ...@@ -2400,30 +2404,34 @@ bool SystemTools::CopyFileAlways(const std::string& source,
} }
// If files are the same do not copy // If files are the same do not copy
if (SystemTools::SameFile(source, real_destination)) { if (SystemTools::SameFile(source, real_destination)) {
return true; return status;
} }
// Create destination directory // Create destination directory
if (!destination_dir.empty()) {
SystemTools::MakeDirectory(destination_dir); status = SystemTools::MakeDirectory(destination_dir);
if (!status) {
if (!SystemTools::CloneFileContent(source, real_destination)) { return status;
// if cloning did not succeed, fall back to blockwise copy
if (!SystemTools::CopyFileContentBlockwise(source, real_destination)) {
return false;
} }
} }
status = SystemTools::CloneFileContent(source, real_destination);
// if cloning did not succeed, fall back to blockwise copy
if (!status) {
status = SystemTools::CopyFileContentBlockwise(source, real_destination);
}
if (!status) {
return status;
}
} }
if (perms) { if (perms) {
if (!SystemTools::SetPermissions(real_destination, perm)) { status = SystemTools::SetPermissions(real_destination, perm);
return false;
}
} }
return true; return status;
} }
bool SystemTools::CopyAFile(const std::string& source, Status SystemTools::CopyAFile(std::string const& source,
const std::string& destination, bool always) std::string const& destination, bool always)
{ {
if (always) { if (always) {
return SystemTools::CopyFileAlways(source, destination); return SystemTools::CopyFileAlways(source, destination);
...@@ -2436,18 +2444,21 @@ bool SystemTools::CopyAFile(const std::string& source, ...@@ -2436,18 +2444,21 @@ bool SystemTools::CopyAFile(const std::string& source,
* Copy a directory content from "source" directory to the directory named by * Copy a directory content from "source" directory to the directory named by
* "destination". * "destination".
*/ */
bool SystemTools::CopyADirectory(const std::string& source, Status SystemTools::CopyADirectory(std::string const& source,
const std::string& destination, bool always) std::string const& destination, bool always)
{ {
Status status;
Directory dir; Directory dir;
if (!dir.Load(source)) { status = dir.Load(source);
return false; if (!status) {
return status;
} }
size_t fileNum; status = SystemTools::MakeDirectory(destination);
if (!SystemTools::MakeDirectory(destination)) { if (!status) {
return false; return status;
} }
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 && if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 &&
strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) { strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) {
std::string fullPath = source; std::string fullPath = source;
...@@ -2457,18 +2468,20 @@ bool SystemTools::CopyADirectory(const std::string& source, ...@@ -2457,18 +2468,20 @@ bool SystemTools::CopyADirectory(const std::string& source,
std::string fullDestPath = destination; std::string fullDestPath = destination;
fullDestPath += "/"; fullDestPath += "/";
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) { status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
return false; if (!status) {
return status;
} }
} else { } else {
if (!SystemTools::CopyAFile(fullPath, destination, always)) { status = SystemTools::CopyAFile(fullPath, destination, always);
return false; if (!status) {
return status;
} }
} }
} }
} }
return true; return status;
} }
// return size of file; also returns zero if no file exists // return size of file; also returns zero if no file exists
......
...@@ -562,8 +562,8 @@ public: ...@@ -562,8 +562,8 @@ public:
* Copy the source file to the destination file only * Copy the source file to the destination file only
* if the two files differ. * if the two files differ.
*/ */
static bool CopyFileIfDifferent(const std::string& source, static Status CopyFileIfDifferent(std::string const& source,
const std::string& destination); std::string const& destination);
/** /**
* Compare the contents of two files. Return true if different * Compare the contents of two files. Return true if different
...@@ -581,13 +581,13 @@ public: ...@@ -581,13 +581,13 @@ public:
/** /**
* Blockwise copy source to destination file * Blockwise copy source to destination file
*/ */
static bool CopyFileContentBlockwise(const std::string& source, static Status CopyFileContentBlockwise(std::string const& source,
const std::string& destination); std::string const& destination);
/** /**
* Clone the source file to the destination file * Clone the source file to the destination file
*/ */
static bool CloneFileContent(const std::string& source, static Status CloneFileContent(std::string const& source,
const std::string& destination); std::string const& destination);
/** /**
* Return true if the two files are the same file * Return true if the two files are the same file
...@@ -597,16 +597,16 @@ public: ...@@ -597,16 +597,16 @@ public:
/** /**
* Copy a file. * Copy a file.
*/ */
static bool CopyFileAlways(const std::string& source, static Status CopyFileAlways(std::string const& source,
const std::string& destination); std::string const& destination);
/** /**
* Copy a file. If the "always" argument is true the file is always * Copy a file. If the "always" argument is true the file is always
* copied. If it is false, the file is copied only if it is new or * copied. If it is false, the file is copied only if it is new or
* has changed. * has changed.
*/ */
static bool CopyAFile(const std::string& source, static Status CopyAFile(std::string const& source,
const std::string& destination, bool always = true); std::string const& destination, bool always = true);
/** /**
* Copy content directory to another directory with all files and * Copy content directory to another directory with all files and
...@@ -614,9 +614,9 @@ public: ...@@ -614,9 +614,9 @@ public:
* always copied. If it is false, only files that have changed or * always copied. If it is false, only files that have changed or
* are new are copied. * are new are copied.
*/ */
static bool CopyADirectory(const std::string& source, static Status CopyADirectory(std::string const& source,
const std::string& destination, std::string const& destination,
bool always = true); bool always = true);
/** /**
* Remove a file * Remove a file
......
...@@ -120,7 +120,7 @@ int _copyDirectoryTest() ...@@ -120,7 +120,7 @@ int _copyDirectoryTest()
std::cerr << destination << " shouldn't exist before test" << std::endl; std::cerr << destination << " shouldn't exist before test" << std::endl;
return 2; return 2;
} }
const bool copysuccess = SystemTools::CopyADirectory(source, destination); const Status copysuccess = SystemTools::CopyADirectory(source, destination);
const bool destinationexists = SystemTools::PathExists(destination); const bool destinationexists = SystemTools::PathExists(destination);
if (copysuccess) { if (copysuccess) {
std::cerr << "CopyADirectory should have returned false" << std::endl; std::cerr << "CopyADirectory should have returned false" << std::endl;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment