Przeglądaj źródła

2007-09-15 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Fixed: control file cannot be saved in the second attempt 
because of
	the nature of win32's rename() function.
	* src/File.{h, cc} (renameTo): New function. Thanks to Ross.
	* src/DefaultBtProgressInfoFile.cc: Use File::renameTo()
	* src/SegmentMan.cc: Use File::renameTo()
	* test/FileTest.cc (testRenameTo): Added.
Tatsuhiro Tsujikawa 18 lat temu
rodzic
commit
39f30e46e7
6 zmienionych plików z 58 dodań i 2 usunięć
  1. 9 0
      ChangeLog
  2. 1 1
      src/DefaultBtProgressInfoFile.cc
  3. 23 0
      src/File.cc
  4. 2 0
      src/File.h
  5. 1 1
      src/SegmentMan.cc
  6. 22 0
      test/FileTest.cc

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+2007-09-15  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Fixed: control file cannot be saved in the second attempt because of
+	the nature of win32's rename() function.
+	* src/File.{h, cc} (renameTo): New function. Thanks to Ross.
+	* src/DefaultBtProgressInfoFile.cc: Use File::renameTo()
+	* src/SegmentMan.cc: Use File::renameTo()
+	* test/FileTest.cc (testRenameTo): Added.
+
 2007-09-14  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Fixed the compilation error on 64bit platform.

+ 1 - 1
src/DefaultBtProgressInfoFile.cc

@@ -92,7 +92,7 @@ void DefaultBtProgressInfoFile::save() {
 			filename.c_str(), strerror(errno));
   }
 
-  if(rename(filenameTemp.c_str(), filename.c_str()) == -1) {
+  if(!File(filenameTemp).renameTo(filename)) {
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
 			filename.c_str(), strerror(errno));
   }

+ 23 - 0
src/File.cc

@@ -37,6 +37,11 @@
 #include "a2io.h"
 #include <libgen.h>
 
+#ifdef __MINGW32__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif // __MINGW32__
+
 File::File(const string& name):name(name) {}
 
 File::~File() {}
@@ -140,3 +145,21 @@ bool File::isDir(const string& filename)
 {
   return File(filename).isDir();
 }
+
+bool File::renameTo(const string& dest)
+{
+#ifdef __MINGW32__
+  /* MinGW's rename() doesn't delete an existing destination */
+  if (_access(dest.c_str(), 0) == 0) {
+    if (_unlink(dest.c_str()) != 0) {
+      return false;
+    }
+  }
+#endif // __MINGW32__
+  if(rename(name.c_str(), dest.c_str()) == 0) {
+    name = dest;
+    return true;
+  } else {
+    return false;
+  }
+}

+ 2 - 0
src/File.h

@@ -96,6 +96,8 @@ public:
   string getDirname() const;
 
   static bool isDir(const string& filename);
+
+  bool renameTo(const string& dest);
 };
 
 #endif // _D_FILE_H_

+ 1 - 1
src/SegmentMan.cc

@@ -143,7 +143,7 @@ void SegmentMan::save() const {
 			segFilename.c_str(), strerror(errno));
   }
 
-  if(rename(segFilenameTemp.c_str(), segFilename.c_str()) == -1) {
+  if(!File(segFilenameTemp).renameTo(segFilename)) {
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
 			segFilename.c_str(), strerror(errno));
   }

+ 22 - 0
test/FileTest.cc

@@ -18,6 +18,7 @@ class FileTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testMkdir);
   CPPUNIT_TEST(testGetDirname);
   CPPUNIT_TEST(testGetBasename);
+  CPPUNIT_TEST(testRenameTo);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -33,6 +34,7 @@ public:
   void testMkdir();
   void testGetDirname();
   void testGetBasename();
+  void testRenameTo();
 };
 
 
@@ -132,3 +134,23 @@ void FileTest::testGetBasename()
   File f("/tmp/dist/aria2.tar.bz2");
   CPPUNIT_ASSERT_EQUAL(string("aria2.tar.bz2"), f.getBasename());
 }
+
+void FileTest::testRenameTo()
+{
+  string fname = "FileTest_testRenameTo.txt";
+  ofstream of(fname.c_str());
+  of.close();
+
+  File f(fname);
+  string fnameTo = "FileTest_testRenameTo_dest.txt";
+  CPPUNIT_ASSERT(f.renameTo(fnameTo));
+  CPPUNIT_ASSERT(f.exists());
+  CPPUNIT_ASSERT(!File(fname).exists());
+  CPPUNIT_ASSERT_EQUAL(fnameTo, f.getBasename());
+
+  // to see renameTo() work even when the destination file exists
+  of.open(fname.c_str());
+  of.close();
+  
+  CPPUNIT_ASSERT(f.renameTo(fname));
+}