From ce10bfbe252d5598bbb559c6ce55aed1b9393227 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Fri, 18 Nov 2016 11:11:34 +0100 Subject: [PATCH] somewhat self-cleaning temp dir --- src/io/filesystem.cpp | 58 ++++++++++++++++++++++++++++++++------- src/io/filesystem.hpp | 21 ++++++++++++++ src/net/tcp.cpp | 13 ++++++++- src/net/tcp.hpp | 3 +- tst/io/FilesystemTest.cpp | 17 ++++-------- tst/io/FilesystemTest.hpp | 7 +++-- 6 files changed, 94 insertions(+), 25 deletions(-) diff --git a/src/io/filesystem.cpp b/src/io/filesystem.cpp index b0a9126..5a4515e 100644 --- a/src/io/filesystem.cpp +++ b/src/io/filesystem.cpp @@ -2,7 +2,10 @@ #include #include +#include #include +#include +#include #ifdef _WIN32 # include # include @@ -13,6 +16,8 @@ #endif #include +using namespace std; + namespace blank { @@ -40,7 +45,7 @@ namespace { return S_ISREG(info.st_mode); } #endif - std::time_t get_mtime(const Stat &info) { + time_t get_mtime(const Stat &info) { #ifdef __APPLE__ return info.st_mtimespec.tv_sec; #else @@ -65,7 +70,7 @@ bool is_file(const char *path) { return is_file(info); } -std::time_t file_mtime(const char *path) { +time_t file_mtime(const char *path) { Stat info; if (do_stat(path, info) != 0) { return 0; @@ -84,7 +89,7 @@ bool make_dir(const char *path) { } -bool make_dirs(const std::string &path) { +bool make_dirs(const string &path) { if (make_dir(path)) { return true; } @@ -99,7 +104,7 @@ bool make_dirs(const std::string &path) { #else auto pos = path.find_last_of('/'); #endif - if (pos == std::string::npos) { + if (pos == string::npos) { return false; } if (pos == path.length() - 1) { @@ -109,7 +114,7 @@ bool make_dirs(const std::string &path) { #else pos = path.find_last_of('/', pos - 1); #endif - if (pos == std::string::npos) { + if (pos == string::npos) { return false; } } @@ -132,16 +137,16 @@ bool make_dirs(const std::string &path) { } -bool remove_file(const std::string &path) { +bool remove_file(const string &path) { return remove(path.c_str()) == 0; } -bool remove_dir(const std::string &path) { +bool remove_dir(const string &path) { #ifdef _WIN32 // shamelessly stolen from http://www.codeguru.com/forum/showthread.php?t=239271 - const std::string pattern = path + "\\*.*"; + const string pattern = path + "\\*.*"; WIN32_FIND_DATA info; HANDLE file = FindFirstFile(pattern.c_str(), &info); if (file == INVALID_HANDLE_VALUE) { @@ -156,7 +161,7 @@ bool remove_dir(const std::string &path) { ) { continue; } - const std::string sub_path = path + '\\' + info.cFileName; + const string sub_path = path + '\\' + info.cFileName; if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (!remove_dir(sub_path)) { return false; @@ -192,7 +197,7 @@ bool remove_dir(const std::string &path) { ) { continue; } - const std::string sub_path = path + '/' + entry->d_name; + const string sub_path = path + '/' + entry->d_name; if (is_dir(sub_path)) { if (!remove_dir(sub_path)) { return false; @@ -208,4 +213,37 @@ bool remove_dir(const std::string &path) { #endif } + +TempDir::TempDir() { +#if _DEFAULT_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 200809L + char tmpl[] = "blank.XXXXXX"; + const char *name = mkdtemp(tmpl); + if (!name) { + throw runtime_error("unable to create temporary directory"); + } + path = name; +#else + char name[L_tmpnam]; + tmpnam(name); + constexpr int max_tries = 10; + int tries = 0; + while (!make_dirs(name) && tries < max_tries) { + tmpnam(name); + ++tries; + } + if (tries == max_tries) { + throw runtime_error("unable to create temporary directory"); + } +#endif + path = name; +} + +TempDir::~TempDir() { + try { + remove_dir(path); + } catch (...) { + cerr << "warning: could not remove temp dir " << path << endl; + } +} + } diff --git a/src/io/filesystem.hpp b/src/io/filesystem.hpp index 2af55fc..d7fe184 100644 --- a/src/io/filesystem.hpp +++ b/src/io/filesystem.hpp @@ -42,6 +42,27 @@ bool remove_file(const std::string &); /// @return true if the directory was completely removed bool remove_dir(const std::string &); + +/// Create a temporary directory with lifetime tie to the instance's. +/// Note that the directory may survive its object if removal fails +/// for any reason, e.g. another process changing permissions. +class TempDir { + +public: + TempDir(); + ~TempDir(); + + TempDir(const TempDir &) = delete; + TempDir &operator =(const TempDir &) = delete; + +public: + const std::string &Path() const noexcept { return path; } + +private: + std::string path; + +}; + } #endif diff --git a/src/net/tcp.cpp b/src/net/tcp.cpp index f9e039b..7d8862a 100644 --- a/src/net/tcp.cpp +++ b/src/net/tcp.cpp @@ -27,6 +27,18 @@ Socket::Socket(unsigned short port) } } +Socket::Socket(const string &host, unsigned short port) +: sock(nullptr) { + IPaddress ip; + if (SDLNet_ResolveHost(&ip, host.c_str(), port) == -1) { + throw NetError("failed to resolve host " + host); + } + sock = SDLNet_TCP_Open(&ip); + if (!sock) { + throw NetError("failed to connect to " + host + ':' + to_string(port)); + } +} + Socket::Socket(TCPsocket sock) : sock(sock) { @@ -86,7 +98,6 @@ int Socket::RemoveFrom(SDLNet_SocketSet set) { Pool::Pool(int max_conn, size_t buf_siz) : set(SDLNet_AllocSocketSet(max_conn)) -, buffer(buf_siz, '\0') , connections() , use_conn(0) , max_conn(max_conn) diff --git a/src/net/tcp.hpp b/src/net/tcp.hpp index 5b5f878..512beb9 100644 --- a/src/net/tcp.hpp +++ b/src/net/tcp.hpp @@ -18,6 +18,8 @@ public: Socket(); /// create TCP socket bound to given port explicit Socket(unsigned short port); + /// connect to given host:port + Socket(const std::string &host, unsigned short port); private: /// wrap given SDLNet TCP socket /// for use with Accept() @@ -112,7 +114,6 @@ public: private: SDLNet_SocketSet set; - std::string buffer; ConnectionSet connections; int use_conn; int max_conn; diff --git a/tst/io/FilesystemTest.cpp b/tst/io/FilesystemTest.cpp index cd4e0ab..106ff71 100644 --- a/tst/io/FilesystemTest.cpp +++ b/tst/io/FilesystemTest.cpp @@ -13,24 +13,19 @@ namespace blank { namespace test { void FilesystemTest::setUp() { - test_dir = "test-dir"; - CPPUNIT_ASSERT_MESSAGE( - "failed to create test dir", - make_dir(test_dir)); + test_dir.reset(new TempDir()); } void FilesystemTest::tearDown() { - CPPUNIT_ASSERT_MESSAGE( - "failed to remove test dir", - remove_dir(test_dir)); + test_dir.reset(); } void FilesystemTest::testFile() { #ifdef _WIN32 - const string test_file = test_dir + "\\test-file.txt"; + const string test_file = test_dir->Path() + "\\test-file.txt"; #else - const string test_file = test_dir + "/test-file"; + const string test_file = test_dir->Path() + "/test-file"; #endif CPPUNIT_ASSERT_MESSAGE( @@ -76,11 +71,11 @@ void FilesystemTest::testFile() { void FilesystemTest::testDirectory() { #ifdef _WIN32 - const string test_subdir = test_dir + "\\a"; + const string test_subdir = test_dir->Path() + "\\a"; const string test_subsubdir = test_subdir + "\\b"; const string test_file = test_subsubdir + "\\c.txt"; #else - const string test_subdir = test_dir + "/a"; + const string test_subdir = test_dir->Path() + "/a"; const string test_subsubdir = test_subdir + "/b"; const string test_file = test_subsubdir + "/c"; #endif diff --git a/tst/io/FilesystemTest.hpp b/tst/io/FilesystemTest.hpp index 2b30c5e..60da69c 100644 --- a/tst/io/FilesystemTest.hpp +++ b/tst/io/FilesystemTest.hpp @@ -1,11 +1,14 @@ #ifndef BLANK_TEST_IO_FILESYSTEMTEST_HPP #define BLANK_TEST_IO_FILESYSTEMTEST_HPP +#include "io/filesystem.hpp" + +#include #include #include -namespace blank { +namespace blank { namespace test { class FilesystemTest @@ -26,7 +29,7 @@ public: void testDirectory(); private: - std::string test_dir; + std::unique_ptr test_dir; }; -- 2.39.2