From c79b872ca3f0480f9e23d54be2334ff5cca481ec Mon Sep 17 00:00:00 2001 From: Gerd von Egidy Date: Wed, 10 Mar 2010 17:58:50 +0100 Subject: [PATCH] implement unlink and move, add tests for them --- src/tmpfstream.hpp | 2 +- src/tmpfstream_impl.hpp | 26 ++++++++- test/test_tmpfstream.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 158 insertions(+), 4 deletions(-) diff --git a/src/tmpfstream.hpp b/src/tmpfstream.hpp index 40b5804..024b0e5 100644 --- a/src/tmpfstream.hpp +++ b/src/tmpfstream.hpp @@ -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 tmpofstream; diff --git a/src/tmpfstream_impl.hpp b/src/tmpfstream_impl.hpp index 83a7d33..1549b53 100644 --- a/src/tmpfstream_impl.hpp +++ b/src/tmpfstream_impl.hpp @@ -59,7 +59,10 @@ bool tmpfstreamTempl::open(const std::string& tmpnametemplate, template< typename Device, typename Tr, typename Alloc > bool tmpfstreamTempl::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::unlink() } template< typename Device, typename Tr, typename Alloc > -bool tmpfstreamTempl::move_to(const std::string& targetpath, +bool tmpfstreamTempl::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; + } } } diff --git a/test/test_tmpfstream.cpp b/test/test_tmpfstream.cpp index d7e9e21..123fe88 100644 --- a/test/test_tmpfstream.cpp +++ b/test/test_tmpfstream.cpp @@ -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() -- 1.7.1