+
+bool remove_file(const string &path) {
+ return remove(path.c_str()) == 0;
+}
+
+
+bool remove_dir(const string &path) {
+#ifdef _WIN32
+
+ // shamelessly stolen from http://www.codeguru.com/forum/showthread.php?t=239271
+ const string pattern = path + "\\*.*";
+ WIN32_FIND_DATA info;
+ HANDLE file = FindFirstFile(pattern.c_str(), &info);
+ if (file == INVALID_HANDLE_VALUE) {
+ // already non-existing
+ return true;
+ }
+
+ do {
+ if (
+ strncmp(info.cFileName, ".", 2) == 0 ||
+ strncmp(info.cFileName, "..", 3) == 0
+ ) {
+ continue;
+ }
+ const string sub_path = path + '\\' + info.cFileName;
+ if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ if (!remove_dir(sub_path)) {
+ return false;
+ }
+ } else {
+ if (!SetFileAttributes(sub_path.c_str(), FILE_ATTRIBUTE_NORMAL)) {
+ return false;
+ }
+ if (!remove_file(sub_path)) {
+ return false;
+ }
+ }
+ } while (FindNextFile(file, &info));
+ FindClose(file);
+
+ DWORD error = GetLastError();
+ if (error != ERROR_NO_MORE_FILES) {
+ return false;
+ }
+ // is this (NORMAL vs DIRECTORY) really correct?
+ if (!SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL)) {
+ return false;
+ }
+ return RemoveDirectory(path.c_str());
+
+#else
+
+ DIR *dir = opendir(path.c_str());
+ for (dirent *entry = readdir(dir); entry != nullptr; entry = readdir(dir)) {
+ if (
+ strncmp(entry->d_name, ".", 2) == 0 ||
+ strncmp(entry->d_name, "..", 3) == 0
+ ) {
+ continue;
+ }
+ const string sub_path = path + '/' + entry->d_name;
+ if (is_dir(sub_path)) {
+ if (!remove_dir(sub_path)) {
+ return false;
+ }
+ } else {
+ if (!remove_file(sub_path)) {
+ return false;
+ }
+ }
+ }
+ return remove(path.c_str()) == 0;
+
+#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;
+ }
+}
+