瀏覽代碼

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.

Brad King 24 年之前
父節點
當前提交
bfcf4b02bf
共有 1 個文件被更改,包括 15 次插入36 次删除
  1. 15 36
      Source/cmSystemTools.cxx

+ 15 - 36
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,
 void cmSystemTools::cmCopyFile(const char* source,
                                const char* destination)
                                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)
   if(!fin)
     {
     {
     cmSystemTools::Error("CopyFile failed to open input file \"",
     cmSystemTools::Error("CopyFile failed to open input file \"",
@@ -866,38 +858,25 @@ void cmSystemTools::cmCopyFile(const char* source,
     return;
     return;
     }
     }
   std::ofstream fout(destination,
   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)
   if(!fout)
     {
     {
     cmSystemTools::Error("CopyFile failed to open output file \"",
     cmSystemTools::Error("CopyFile failed to open output file \"",
                          destination, "\"");
                          destination, "\"");
     return;
     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());
       }
       }
     }
     }
 }
 }