implement unlink and move, add tests for them
authorGerd von Egidy <gerd.von.egidy@intra2net.com>
Wed, 10 Mar 2010 16:58:50 +0000 (17:58 +0100)
committerGerd von Egidy <gerd.von.egidy@intra2net.com>
Wed, 10 Mar 2010 16:58:50 +0000 (17:58 +0100)
src/tmpfstream.hpp
src/tmpfstream_impl.hpp
test/test_tmpfstream.cpp

index 40b5804..024b0e5 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     bool unlink();
 
-    bool move_to(const std::string& targetpath, bool overwrite);
+    bool move(const std::string& targetpath, bool overwrite);
 };
 
 typedef tmpfstreamTempl<bio::file_descriptor_sink> tmpofstream;
index 83a7d33..1549b53 100644 (file)
@@ -59,7 +59,10 @@ bool tmpfstreamTempl<Device,Tr,Alloc>::open(const std::string& tmpnametemplate,
 template< typename Device, typename Tr, typename Alloc >
 bool tmpfstreamTempl<Device,Tr,Alloc>::set_file_mode(int mode)
 {
-
+    if (!get_tmp_filename().empty())
+        return I2n::chmod(get_tmp_filename(),mode);
+    else
+        return false;
 }
 
 template< typename Device, typename Tr, typename Alloc >
@@ -72,10 +75,29 @@ bool tmpfstreamTempl<Device,Tr,Alloc>::unlink()
 }
 
 template< typename Device, typename Tr, typename Alloc >
-bool tmpfstreamTempl<Device,Tr,Alloc>::move_to(const std::string& targetpath, 
+bool tmpfstreamTempl<Device,Tr,Alloc>::move(const std::string& targetpath, 
                                           bool overwrite)
 {
+    if (get_tmp_filename().empty())
+        return false;
 
+    if (overwrite)
+    {
+        // this overwrites an already existing target without further warning
+        // other errors possible, see errno
+        int res = ::rename( get_tmp_filename().c_str(), targetpath.c_str() );
+        return (res == 0);
+    }
+    else
+    {
+        // fails if the target already exists
+        // other errors possible, see errno
+        int res = ::link( get_tmp_filename().c_str(), targetpath.c_str() );
+        if (res != 0)
+            return false;
+        ::unlink(get_tmp_filename().c_str());
+        return true;
+    }
 }
 
 }
index d7e9e21..123fe88 100644 (file)
@@ -29,7 +29,7 @@ namespace bio = boost::iostreams;
 
 BOOST_AUTO_TEST_SUITE(TestTmpfstream)
 
-BOOST_AUTO_TEST_CASE(Tmpfstream)
+BOOST_AUTO_TEST_CASE(Tmpofstream)
 {
     tmpofstream tmpf("./tmp.XXXXXX");
 
@@ -62,5 +62,137 @@ BOOST_AUTO_TEST_CASE(Tmpfstream)
 
 } 
 
+BOOST_AUTO_TEST_CASE(TmpofstreamUnlink)
+{
+    tmpofstream tmpf("./tmp.XXXXXX");
+
+    BOOST_CHECK_EQUAL( true, tmpf.is_open() );
+
+    Stat stat(tmpf.get_tmp_filename());
+    BOOST_CHECK_EQUAL( true, (bool)stat );
+    BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
+
+    tmpf << "hello world" << endl;
+
+    // keep open but delete file
+    tmpf.unlink();
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    // writing to already deleted file
+    // POSIX explicitly allows this
+    tmpf << "hello world" << endl;
+    tmpf.flush();
+    BOOST_CHECK_EQUAL( true, tmpf.good() );
+
+    // file still gone after closing
+    tmpf.close();
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+} 
+
+BOOST_AUTO_TEST_CASE(TmpofstreamMove1)
+{
+    // just to be sure
+    unlink(".foobar");
+
+    tmpofstream tmpf("./tmp.XXXXXX");
+
+    BOOST_CHECK_EQUAL( true, tmpf.is_open() );
+
+    Stat stat(tmpf.get_tmp_filename());
+    BOOST_CHECK_EQUAL( true, (bool)stat );
+    BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
+
+    tmpf << "hello world" << endl;
+    tmpf.flush();
+
+    BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",false) );
+
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    Stat stat2(".foobar");
+    BOOST_CHECK_EQUAL( true, (bool)stat2 );
+
+    tmpf.close();
+
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    stat2.recheck();
+    BOOST_CHECK_EQUAL( true, (bool)stat2 );
+
+    unlink(".foobar");
+} 
+
+BOOST_AUTO_TEST_CASE(TmpofstreamMove2)
+{
+    // just to be sure
+    unlink(".foobar");
+
+    tmpofstream tmpf("./tmp.XXXXXX");
+
+    BOOST_CHECK_EQUAL( true, tmpf.is_open() );
+
+    Stat stat(tmpf.get_tmp_filename());
+    BOOST_CHECK_EQUAL( true, (bool)stat );
+    BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
+
+    tmpf << "hello world" << endl;
+    tmpf.flush();
+
+    BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",true) );
+
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    Stat stat2(".foobar");
+    BOOST_CHECK_EQUAL( true, (bool)stat2 );
+
+    tmpf.close();
+
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    stat2.recheck();
+    BOOST_CHECK_EQUAL( true, (bool)stat2 );
+
+    unlink(".foobar");
+} 
+
+BOOST_AUTO_TEST_CASE(TmpofstreamMoveOverwrite)
+{
+    // prepare other file
+    write_file(".foobar","blah");
+
+    tmpofstream tmpf("./tmp.XXXXXX");
+
+    BOOST_CHECK_EQUAL( true, tmpf.is_open() );
+
+    Stat stat(tmpf.get_tmp_filename());
+    BOOST_CHECK_EQUAL( true, (bool)stat );
+    BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
+
+    tmpf << "hello world" << endl;
+    tmpf.flush();
+
+    // no overwrite fails
+    BOOST_CHECK_EQUAL( false, tmpf.move(".foobar",false) );
+
+    // overwrite succeeds
+    BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",true) );
+
+    stat.recheck();
+    BOOST_CHECK_EQUAL( false, (bool)stat );
+
+    Stat stat2(".foobar");
+    BOOST_CHECK_EQUAL( true, (bool)stat2 );
+
+    tmpf.close();
+
+    unlink(".foobar");
+} 
+
 
 BOOST_AUTO_TEST_SUITE_END()