From c18f069c588dfcce5afec95960a3c4646e406775 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Mon, 22 Jul 2019 09:33:19 +0200 Subject: [PATCH] Windows: add the recoll temporary files directory to skippedPaths --- src/common/rclconfig.cpp | 3 + src/utils/rclutil.cpp | 124 +++++++++++++++++++++++---------------- src/utils/rclutil.h | 14 +++-- 3 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index 14a66feb..d5e25363 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -1559,6 +1559,9 @@ vector RclConfig::getSkippedPaths() const // don't do this. skpl.push_back(getDbDir()); skpl.push_back(getConfDir()); +#ifdef _WIN32 + skpl.push_back(TempFile::rcltmpdir()); +#endif if (getCacheDir().compare(getConfDir())) { skpl.push_back(getCacheDir()); } diff --git a/src/utils/rclutil.cpp b/src/utils/rclutil.cpp index 9a65d9d6..8ae7f4bf 100644 --- a/src/utils/rclutil.cpp +++ b/src/utils/rclutil.cpp @@ -83,7 +83,7 @@ static bool path_isdriveabs(const string& s) #include #pragma comment(lib, "shlwapi.lib") -string path_thisexecpath() +static string path_thisexecpath() { wchar_t text[MAX_PATH]; GetModuleFileNameW(NULL, text, MAX_PATH); @@ -100,25 +100,38 @@ string path_thisexecpath() return path; } -string path_wingettempfilename(wchar_t *pref) + +// On Windows, we ese a subdirectory named "rcltmp" inside the windows +// temp location to create the temporary files in. +static const string& path_wingetrcltmpdir() { - // Use a subdirectory named "rcltmp" inside the windows temp - // location. - wchar_t dbuf[MAX_PATH + 1]; - GetTempPathW(MAX_PATH + 1, dbuf); - string tdir; - wchartoutf8(dbuf, tdir); - tdir = path_cat(tdir, "rcltmp");; - if (!path_exists(tdir)) { - if (path_makepath(tdir, 0700)) { - LOGSYSERR("path_wingettempfilename", "path_makepath", tdir); + // Constant: only need to compute once + static string tdir; + if (tdir.empty()) { + wchar_t dbuf[MAX_PATH + 1]; + GetTempPathW(MAX_PATH + 1, dbuf); + wchartoutf8(dbuf, tdir); + tdir = path_cat(tdir, "rcltmp");; + if (!path_exists(tdir)) { + if (path_makepath(tdir, 0700)) { + LOGSYSERR("path_wingettempfilename", "path_makepath", tdir); + } } } + return tdir; +} + +static bool path_gettempfilename(string& filename, string& reason) +{ + string tdir = path_wingetrcltmpdir(); + wchar_t dbuf[MAX_PATH + 1]; utf8towchar(tdir, dbuf, MAX_PATH); + wchar_t buf[MAX_PATH + 1]; - GetTempFileNameW(dbuf, pref, 0, buf); - string filename; + static wchar_t prefix[]{L"rcl"}; + GetTempFileNameW(dbuf, prefix, 0, buf); wchartoutf8(buf, filename); + // Windows will have created a temp file, we delete it. if (!DeleteFileW(buf)) { LOGSYSERR("path_wingettempfilename", "DeleteFileW", filename); @@ -126,10 +139,35 @@ string path_wingettempfilename(wchar_t *pref) LOGDEB1("path_wingettempfilename: DeleteFile " << filename << " Ok\n"); } path_slashize(filename); - return filename; + return true; } -#endif // _WIN32 +#else // _WIN32 above + +static bool path_gettempfilename(string& filename, string& reason) +{ + filename = path_cat(tmplocation(), "rcltmpfXXXXXX"); + char *cp = strdup(filename.c_str()); + if (!cp) { + reason = "Out of memory (for file name !)\n"; + return false; + } + + // Using mkstemp this way is awful (bot the suffix adding and + // using mkstemp() instead of mktemp just to avoid the warnings) + int fd; + if ((fd = mkstemp(cp)) < 0) { + free(cp); + reason = "TempFileInternal: mkstemp failed\n"; + return false; + } + close(fd); + unlink(cp); + filename = cp; + free(cp); + return true; +} +#endif // posix // Check if path is either non-existing or an empty directory. bool path_empty(const string& path) @@ -259,21 +297,21 @@ bool maketmpdir(string& tdir, string& reason) // There is a race condition between name computation and // mkdir. try to make sure that we at least don't shoot ourselves // in the foot -#if !defined(HAVE_MKDTEMP) || defined(_WIN32) +#if !defined(HAVE_MKDTEMP) static std::mutex mmutex; std::unique_lock lock(mmutex); #endif if (! #ifdef HAVE_MKDTEMP - mkdtemp(cp) + mkdtemp(cp) #else - mktemp(cp) + mktemp(cp) #endif // HAVE_MKDTEMP - ) { + ) { free(cp); reason = "maketmpdir: mktemp failed for [" + tdir + "] : " + - strerror(errno); + strerror(errno); tdir.erase(); return false; } @@ -285,8 +323,9 @@ bool maketmpdir(string& tdir, string& reason) // in the foot static std::mutex mmutex; std::unique_lock lock(mmutex); - static wchar_t tmpbasename[]{L"rcltmp"}; - tdir = path_wingettempfilename(tmpbasename); + if (!path_gettempfilename(tdir, reason)) { + return false; + } #endif // At this point the directory does not exist yet except if we used @@ -356,32 +395,10 @@ TempFile::Internal::Internal(const string& suffix) static std::mutex mmutex; std::unique_lock lock(mmutex); -#ifndef _WIN32 - string filename = path_cat(tmplocation(), "rcltmpfXXXXXX"); - char *cp = strdup(filename.c_str()); - if (!cp) { - m_reason = "Out of memory (for file name !)\n"; + if (!path_gettempfilename(m_filename, m_reason)) { return; } - - // Using mkstemp this way is awful (bot the suffix adding and - // using mkstemp() instead of mktemp just to avoid the warnings) - int fd; - if ((fd = mkstemp(cp)) < 0) { - free(cp); - m_reason = "TempFileInternal: mkstemp failed\n"; - return; - } - close(fd); - unlink(cp); - filename = cp; - free(cp); -#else - static wchar_t tmpbasename[]{L"rcl"}; - string filename = path_wingettempfilename(tmpbasename); -#endif - - m_filename = filename + suffix; + m_filename += suffix; LOGDEB1("TempFile: filename: " << m_filename << endl); int fd1 = open(m_filename.c_str(), O_CREAT | O_EXCL, 0600); if (fd1 < 0) { @@ -393,6 +410,15 @@ TempFile::Internal::Internal(const string& suffix) } } +const std::string& TempFile::rcltmpdir() +{ +#ifdef _WIN32 + return path_wingetrcltmpdir(); +#else + return tmplocation(); +#endif +} + #ifdef _WIN32 static list remainingTempFileNames; static std::mutex remTmpFNMutex; @@ -423,8 +449,8 @@ TempFile::Internal::~Internal() void TempFile::tryRemoveAgain() { #ifdef _WIN32 - LOGDEB1("TempFile::tryRemoveAgain. List size: " << - remainingTempFileNames.size() << endl); + LOGDEB1("TempFile::tryRemoveAgain. List size: " << + remainingTempFileNames.size() << endl); std::unique_lock lock(remTmpFNMutex); std::list::iterator pos = remainingTempFileNames.begin(); while (pos != remainingTempFileNames.end()) { diff --git a/src/utils/rclutil.h b/src/utils/rclutil.h index 19de72e4..2db003d5 100644 --- a/src/utils/rclutil.h +++ b/src/utils/rclutil.h @@ -58,11 +58,15 @@ public: const std::string& getreason() const; void setnoremove(bool onoff); bool ok() const; - // Attempt to delete all files which could not be deleted on the - // first try (typically on Windows: because they are open by some - // process). Called after clearing the mimeHandler cache. Does - // nothing if not _WIN32 - static void tryRemoveAgain(); + // Attempt to delete all files which could not be deleted on the + // first try (typically on Windows: because they are open by some + // process). Called after clearing the mimeHandler cache. Does + // nothing if not _WIN32 + static void tryRemoveAgain(); + // Also for Windows: for adding the temp files path to the default + // skippedPaths + static const std::string& rcltmpdir(); + class Internal; private: std::shared_ptr m;