summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2002-02-22 15:08:04 (GMT)
committerBrad King <brad.king@kitware.com>2002-02-22 15:08:04 (GMT)
commitbfcf4b02bfa344c335f86ee6734b1d6c651a93ad (patch)
treef169a05e153cdbec6b702da2a30ee7c4a60fe723
parent5cd08d0563c808243cfbac63df7aa57b9a4d9b7b (diff)
downloadCMake-bfcf4b02bfa344c335f86ee6734b1d6c651a93ad.zip
CMake-bfcf4b02bfa344c335f86ee6734b1d6c651a93ad.tar.gz
CMake-bfcf4b02bfa344c335f86ee6734b1d6c651a93ad.tar.bz2
ENH: Another attempt at getting cmCopyFile to work correctly. The previous implementation was correct, but didn't work on HPUX due to stream library bugs. This implementation will hopefully work everywhere.
-rw-r--r--Source/cmSystemTools.cxx51
1 files changed, 15 insertions, 36 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 080efcd..39386cb 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -843,22 +843,14 @@ bool cmSystemTools::FilesDiffer(const char* source,
/**
- * Copy a file named by "source" to the file named by "destination". This
- * implementation makes correct use of the C++ standard file streams to
- * perfectly copy any file with lines of any length (even binary files).
+ * Copy a file named by "source" to the file named by "destination".
*/
void cmSystemTools::cmCopyFile(const char* source,
const char* destination)
{
- // Buffer length is only for block size. Any file would still be copied
- // correctly if this were as small as 2.
- const int buffer_length = 4096;
- char buffer[buffer_length];
- std::ifstream fin(source,
-#ifdef _WIN32
- std::ios::binary |
-#endif
- std::ios::in);
+ const int bufferSize = 4096;
+ char buffer[bufferSize];
+ std::ifstream fin(source, std::ios::binary | std::ios::in);
if(!fin)
{
cmSystemTools::Error("CopyFile failed to open input file \"",
@@ -866,38 +858,25 @@ void cmSystemTools::cmCopyFile(const char* source,
return;
}
std::ofstream fout(destination,
-#ifdef _WIN32
- std::ios::binary |
-#endif
- std::ios::out | std::ios::trunc);
+ std::ios::binary | std::ios::out | std::ios::trunc);
if(!fout)
{
cmSystemTools::Error("CopyFile failed to open output file \"",
destination, "\"");
return;
}
- while(fin.getline(buffer, buffer_length, '\n') || fin.gcount())
+
+ // 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)
{
- unsigned long count = fin.gcount();
- if(fin.eof())
- {
- // Final line, but with no newline.
- fout.write(buffer, count);
- }
- else if ( count == buffer_length - 1 )
- {
- // Part of a line longer than our buffer, clear the fail bit of
- // the stream so that we can continue.
- fin.clear(fin.rdstate() & ~std::ios::failbit);
- fout.write(buffer, count);
- }
- else
+ fin.read(buffer, bufferSize);
+ if(fin.gcount())
{
- // Line on which a newline was encountered. It was read from
- // the stream, but not stored.
- --count;
- fout.write(buffer, count);
- fout << '\n';
+ fout.write(buffer, fin.gcount());
}
}
}