From 1a2fc4e86f5a4b319b1f07c9866c54731d0e3eed Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 10 Apr 2008 12:35:50 +0000 Subject: [PATCH] libi2ncommon: (tomj) added copy_file function --- src/filefunc.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/filefunc.hxx | 2 ++ test/test_filefunc.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/filefunc.cpp b/src/filefunc.cpp index a00c3fe..a8d60fe 100644 --- a/src/filefunc.cpp +++ b/src/filefunc.cpp @@ -441,6 +441,44 @@ bool write_file(const std::string& path, const std::string& data) /** + * Copy file in 4k blocks from source to target. + * Overwrites the target if it already exists. + * + * On error the target file gets removed. + * + * @param src source file + * @param dest target file + * @return true if all is ok, false on error + */ +bool copy_file(const std::string& src, const std::string& dest) +{ + std::ifstream input( src.c_str(), std::ios::in | std::ios::binary ); + if (!input) + return false; + + std::ofstream output( dest.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); + if (!output) + return false; + + char buffer[4096]; + while (input.good()) + { + input.read(buffer, sizeof(buffer)); + output.write(buffer, input.gcount()); + + // Out of disc space? + if (!output.good()) + { + output.close(); + unlink(dest); + return false; + } + } + + return true; +} + +/** * @brief returns the filename part of a path (last component) * @param path the path. * @return the last component of the path. diff --git a/src/filefunc.hxx b/src/filefunc.hxx index 9de7873..c0c01f7 100644 --- a/src/filefunc.hxx +++ b/src/filefunc.hxx @@ -143,6 +143,8 @@ std::string read_file(const std::string& path); bool write_file(const std::string& path, const std::string& data); +bool copy_file(const std::string& src, const std::string& dest); + std::string basename(const std::string& path); std::string dirname(const std::string& path); diff --git a/test/test_filefunc.cpp b/test/test_filefunc.cpp index eef4cde..862f926 100644 --- a/test/test_filefunc.cpp +++ b/test/test_filefunc.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ #define DOUT(msg) do {} while (0) #endif - +using namespace std; using namespace I2n; using namespace CppUnit; @@ -53,7 +54,9 @@ class TestFileFunc : public TestFixture CPPUNIT_TEST(TestUserAndGroupStuff1); CPPUNIT_TEST(TestFileModes1); CPPUNIT_TEST(TestPidOf1); - + CPPUNIT_TEST(TestCopyFileSourceFail); + CPPUNIT_TEST(TestCopyFileDestFail); + CPPUNIT_TEST(TestCopyFileOk); CPPUNIT_TEST_SUITE_END(); @@ -264,8 +267,48 @@ public: CPPUNIT_ASSERT( pos1 != pid_list.end() ); } // eo TestPidOf1() + void TestCopyFileSourceFail() + { + bool res = copy_file("does not exist", "destination"); + CPPUNIT_ASSERT_EQUAL( false, res ); + } + + void TestCopyFileDestFail() + { + bool res = copy_file("/etc/HOSTNAME", "/proc/not/writable"); + CPPUNIT_ASSERT_EQUAL( false, res ); + } + + void TestCopyFileOk() + { + string input = "copy_source"; + string data = "test"; + + long input_size = 0; + ofstream finput(input.c_str()); + if (finput) + { + finput << data; + finput.close(); + input_size = file_size(input); + } + string output = "copy_dest"; + long output_size = 0; + bool res = copy_file(input, output); + if (res) + { + output_size = file_size(output); + } + unlink(input); + unlink(output); + + bool size_is_zero = output_size == 0 ? true : false; + CPPUNIT_ASSERT_EQUAL( true, res ); + CPPUNIT_ASSERT_EQUAL( input_size, output_size ); + CPPUNIT_ASSERT_EQUAL( false, size_is_zero ); + } }; // eo class TestFileFunc CPPUNIT_TEST_SUITE_REGISTRATION(TestFileFunc); -- 1.7.1