]> git.localhorst.tv Git - blank.git/commitdiff
somewhat self-cleaning temp dir
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 18 Nov 2016 10:11:34 +0000 (11:11 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 18 Nov 2016 10:11:34 +0000 (11:11 +0100)
src/io/filesystem.cpp
src/io/filesystem.hpp
src/net/tcp.cpp
src/net/tcp.hpp
tst/io/FilesystemTest.cpp
tst/io/FilesystemTest.hpp

index b0a9126fc5192be77dde7813abaebad3e6e32e82..5a4515e78dfab5629e5ce806b0622d9822829cc2 100644 (file)
@@ -2,7 +2,10 @@
 
 #include <cerrno>
 #include <cstdio>
+#include <cstdlib>
 #include <cstring>
+#include <iostream>
+#include <stdexcept>
 #ifdef _WIN32
 #  include <conio.h>
 #  include <direct.h>
@@ -13,6 +16,8 @@
 #endif
 #include <sys/stat.h>
 
+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;
+       }
+}
+
 }
index 2af55fcce265d866ef33139a470fb0555fc28cd3..d7fe184da71bf0be3c9898261184e5a853a055ab 100644 (file)
@@ -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
index f9e039b96aa3d160d81b5ad9ba1c6ec567a41fa0..7d8862a6697dbd17ade4d1d5dc51e4aff35346ab 100644 (file)
@@ -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)
index 5b5f878ae7160e41dd34282f000f8961cc471134..512beb9bc45b7daf6867d7e62dc594331e5ed28b 100644 (file)
@@ -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;
index cd4e0ab0e882810915911abadddef860fe1dd0d2..106ff71c81d334da90458d139cdd993d29af27ee 100644 (file)
@@ -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
index 2b30c5e13388c0557537dfc670477f4ab89c5e83..60da69c963f7c45467f38f57eb642db8fd501d21 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef BLANK_TEST_IO_FILESYSTEMTEST_HPP
 #define BLANK_TEST_IO_FILESYSTEMTEST_HPP
 
+#include "io/filesystem.hpp"
+
+#include <memory>
 #include <string>
 #include <cppunit/extensions/HelperMacros.h>
 
-namespace blank {
 
+namespace blank {
 namespace test {
 
 class FilesystemTest
@@ -26,7 +29,7 @@ public:
        void testDirectory();
 
 private:
-       std::string test_dir;
+       std::unique_ptr<TempDir> test_dir;
 
 };