From f002679a9cc05ad5a6cf82200508430eedf2e93c Mon Sep 17 00:00:00 2001 From: Gerd von Egidy Date: Thu, 11 Mar 2010 12:31:29 +0100 Subject: [PATCH] implement dirsync() and syncing on tmpfstreams --- src/filefunc.cpp | 19 +++++++++++++++++++ src/filefunc.hxx | 2 ++ src/tmpfstream.hpp | 3 +++ src/tmpfstream_impl.hpp | 24 ++++++++++++++++++++++-- test/test_tmpfstream.cpp | 2 +- 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/filefunc.cpp b/src/filefunc.cpp index c0995e6..b43ef48 100644 --- a/src/filefunc.cpp +++ b/src/filefunc.cpp @@ -616,6 +616,25 @@ std::string normalize_path(const std::string& path) /** + * @brief calls fsync on a given directory to sync all it's metadata + * @param path the path of the directory. + * @return true if successful + */ +bool dirsync(const std::string& path) +{ + // sync the directory the file is in + DIR* dir=opendir(path.c_str()); + if (dir == NULL) + return false; + + int ret=fsync(dirfd(dir)); + + closedir(dir); + + return (ret==0); +} + +/** * @brief changes the file(/path) mode. * @param path the path to change the mode for. * @param mode the new file mode. diff --git a/src/filefunc.hxx b/src/filefunc.hxx index 920a10f..f236246 100644 --- a/src/filefunc.hxx +++ b/src/filefunc.hxx @@ -152,6 +152,8 @@ std::string dirname(const std::string& path); std::string normalize_path(const std::string& path); +bool dirsync(const std::string& path); + bool chmod(const std::string& path, int mode); bool chown(const std::string& path, const I2n::User& user, const I2n::Group& group= I2n::Group()); diff --git a/src/tmpfstream.hpp b/src/tmpfstream.hpp index e4aac49..5f460e8 100644 --- a/src/tmpfstream.hpp +++ b/src/tmpfstream.hpp @@ -40,6 +40,7 @@ class tmpfstreamTempl : public bio::stream private: std::string tmpfilename; bool unlinked; + int fd; public: tmpfstreamTempl() @@ -69,6 +70,8 @@ public: { return unlinked; } bool move(const std::string& targetpath, bool overwrite=false); + + bool sync(); }; template< typename Device, diff --git a/src/tmpfstream_impl.hpp b/src/tmpfstream_impl.hpp index 2de4a91..ee558af 100644 --- a/src/tmpfstream_impl.hpp +++ b/src/tmpfstream_impl.hpp @@ -56,7 +56,7 @@ bool tmpfstreamTempl::open(const std::string& tmpnametemplate, if (mode & std::ios_base::app) flags |= O_APPEND; - int fd=mkostemp(chbuf,flags); + fd=mkostemp(chbuf,flags); tmpfilename=chbuf; delete[] chbuf; @@ -131,13 +131,30 @@ bool tmpfstreamTempl::move(const std::string& targetpath, } template< typename Device, typename Tr, typename Alloc > +bool tmpfstreamTempl::sync() +{ + if (!tmpfstreamTempl::is_open()) + return false; + + tmpfstreamTempl::flush(); + + // sync the file itself + if (fsync(fd) != 0) + return false; + + // sync the dir: both is needed for data + metadata sync + return dirsync(dirname(get_tmp_filename())); +} + +template< typename Device, typename Tr, typename Alloc > void tmpfcopystreamTempl::close() { if (!tmpfstreamTempl::is_open() || tmpfstreamTempl::is_unlinked()) return; - // TODO full sync + if (get_full_sync()) + tmpfstreamTempl::sync(); // close the underlying filedescriptor tmpfstreamTempl::close(); @@ -145,6 +162,9 @@ void tmpfcopystreamTempl::close() tmpfstreamTempl::set_file_mode(filemode_on_close); move(get_original_filename(),true); + + if (get_full_sync()) + dirsync(dirname(get_original_filename())); } } diff --git a/test/test_tmpfstream.cpp b/test/test_tmpfstream.cpp index 24bd8ac..c9e2612 100644 --- a/test/test_tmpfstream.cpp +++ b/test/test_tmpfstream.cpp @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(TmpofstreamMove1) BOOST_CHECK_EQUAL( true, stat.is_regular_file() ); tmpf << "hello world" << endl; - tmpf.flush(); + BOOST_CHECK_EQUAL( true, tmpf.sync() ); BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",false) ); -- 1.7.1