瀏覽代碼

filename::copy_to()

David Rose 16 年之前
父節點
當前提交
d0c99e9288
共有 2 個文件被更改,包括 75 次插入3 次删除
  1. 74 3
      dtool/src/dtoolutil/filename.cxx
  2. 1 0
      dtool/src/dtoolutil/filename.h

+ 74 - 3
dtool/src/dtoolutil/filename.cxx

@@ -2395,15 +2395,86 @@ unlink() const {
 //  Description: Renames the file to the indicated new filename.  If
 //               the new filename is in a different directory, this
 //               will perform a move.  Returns true if successful,
-//               false if failure.
+//               false on failure.
 ////////////////////////////////////////////////////////////////////
 bool Filename::
 rename_to(const Filename &other) const {
   assert(!get_pattern());
   string os_specific = to_os_specific();
   string other_os_specific = other.to_os_specific();
-  return (rename(os_specific.c_str(),
-                 other_os_specific.c_str()) == 0);
+
+  if (rename(os_specific.c_str(),
+             other_os_specific.c_str()) == 0) {
+    // Successfully renamed.
+    return true;
+  }
+
+  // The above might fail if we have tried to move a file to a
+  // different filesystem.  In this case, copy the file into the same
+  // directory first, and then rename it.
+  string dirname = other.get_dirname();
+  if (dirname.empty()) {
+    dirname = ".";
+  }
+  Filename temp = Filename::temporary(dirname, "");
+  temp.set_binary();
+  if (!Filename::binary_filename(*this).copy_to(temp)) {
+    return false;
+  }
+
+  string temp_os_specific = temp.to_os_specific();
+  if (rename(temp_os_specific.c_str(),
+             other_os_specific.c_str()) == 0) {
+    // Successfully renamed.
+    unlink();
+    return true;
+  }
+
+  // Failed.
+  temp.unlink();
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::copy_to
+//       Access: Published
+//  Description: Copies the file to the indicated new filename, by
+//               reading the contents and writing it to the new file.
+//               Returns true if successful, false on failure.
+////////////////////////////////////////////////////////////////////
+bool Filename::
+copy_to(const Filename &other) const {
+  pifstream in;
+  if (!open_read(in)) {
+    return false;
+  }
+
+  pofstream out;
+  if (!other.open_write(out)) {
+    return false;
+  }
+        
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+  
+  in.read(buffer, buffer_size);
+  size_t count = in.gcount();
+  while (count != 0) {
+    out.write(buffer, count);
+    if (out.fail()) {
+      other.unlink();
+      return false;
+    }
+    in.read(buffer, buffer_size);
+    count = in.gcount();
+  }
+
+  if (!in.eof()) {
+    other.unlink();
+    return false;
+  }
+
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
dtool/src/dtoolutil/filename.h

@@ -196,6 +196,7 @@ PUBLISHED:
   bool touch() const;
   bool unlink() const;
   bool rename_to(const Filename &other) const;
+  bool copy_to(const Filename &other) const;
 
   bool make_dir() const;