From: Gerd von Egidy Date: Thu, 11 Mar 2010 10:51:08 +0000 (+0100) Subject: allow double-move X-Git-Tag: v2.6~112^2~3 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=7c4c2ece0ec85dccbe8640a73aff69e45e4b74bb;p=libi2ncommon allow double-move --- diff --git a/src/tmpfstream_impl.hpp b/src/tmpfstream_impl.hpp index 3534178..2de4a91 100644 --- a/src/tmpfstream_impl.hpp +++ b/src/tmpfstream_impl.hpp @@ -101,25 +101,33 @@ bool tmpfstreamTempl::move(const std::string& targetpath, if (get_tmp_filename().empty() || is_unlinked()) return false; + bool success=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); + if (::rename( get_tmp_filename().c_str(), targetpath.c_str() ) == 0) + success=true; } 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; + if (::link( get_tmp_filename().c_str(), targetpath.c_str() ) == 0) + { + success=true; + ::unlink(get_tmp_filename().c_str()); + } + } + + if (success) + { + // store tmpfilename to allow double-move + tmpfilename=targetpath; } - // TODO: set tmpfilename to new name to correctly handle double moves + return success; } template< typename Device, typename Tr, typename Alloc > diff --git a/test/test_tmpfstream.cpp b/test/test_tmpfstream.cpp index 6b3782a..24bd8ac 100644 --- a/test/test_tmpfstream.cpp +++ b/test/test_tmpfstream.cpp @@ -219,6 +219,44 @@ BOOST_AUTO_TEST_CASE(TmpofstreamMoveAfterUnlink) unlink(".foobar"); } +BOOST_AUTO_TEST_CASE(TmpofstreamDoubleMove) +{ + // just to be sure + unlink(".foobar"); + unlink(".foobar2"); + + tmpofstream tmpf("./tmp.XXXXXX"); + + BOOST_CHECK_EQUAL( true, tmpf.is_open() ); + + Stat stat(tmpf.get_tmp_filename()); + BOOST_CHECK_EQUAL( true, (bool)stat ); + + tmpf << "hello world" << endl; + tmpf.flush(); + + BOOST_CHECK_EQUAL( true, tmpf.move(".foobar") ); + + stat.recheck(); + BOOST_CHECK_EQUAL( false, (bool)stat ); + + Stat stat2(".foobar"); + BOOST_CHECK_EQUAL( true, (bool)stat2 ); + + BOOST_CHECK_EQUAL( true, tmpf.move(".foobar2") ); + + stat.recheck(); + BOOST_CHECK_EQUAL( false, (bool)stat ); + + stat2.recheck(); + BOOST_CHECK_EQUAL( false, (bool)stat2 ); + + Stat stat3(".foobar2"); + BOOST_CHECK_EQUAL( true, (bool)stat3 ); + + tmpf.unlink(); +} + BOOST_AUTO_TEST_CASE(TmpfstreamReadWrite) { tmpfstream tmpf("./tmp.XXXXXX",std::ios_base::out | std::ios_base::in );