Windows: add the recoll temporary files directory to skippedPaths

This commit is contained in:
Jean-Francois Dockes 2019-07-22 09:33:19 +02:00
parent 3681e997e0
commit c18f069c58
3 changed files with 87 additions and 54 deletions

View File

@ -1559,6 +1559,9 @@ vector<string> RclConfig::getSkippedPaths() const
// don't do this. // don't do this.
skpl.push_back(getDbDir()); skpl.push_back(getDbDir());
skpl.push_back(getConfDir()); skpl.push_back(getConfDir());
#ifdef _WIN32
skpl.push_back(TempFile::rcltmpdir());
#endif
if (getCacheDir().compare(getConfDir())) { if (getCacheDir().compare(getConfDir())) {
skpl.push_back(getCacheDir()); skpl.push_back(getCacheDir());
} }

View File

@ -83,7 +83,7 @@ static bool path_isdriveabs(const string& s)
#include <Shlwapi.h> #include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "shlwapi.lib")
string path_thisexecpath() static string path_thisexecpath()
{ {
wchar_t text[MAX_PATH]; wchar_t text[MAX_PATH];
GetModuleFileNameW(NULL, text, MAX_PATH); GetModuleFileNameW(NULL, text, MAX_PATH);
@ -100,25 +100,38 @@ string path_thisexecpath()
return path; 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 // Constant: only need to compute once
// location. static string tdir;
wchar_t dbuf[MAX_PATH + 1]; if (tdir.empty()) {
GetTempPathW(MAX_PATH + 1, dbuf); wchar_t dbuf[MAX_PATH + 1];
string tdir; GetTempPathW(MAX_PATH + 1, dbuf);
wchartoutf8(dbuf, tdir); wchartoutf8(dbuf, tdir);
tdir = path_cat(tdir, "rcltmp");; tdir = path_cat(tdir, "rcltmp");;
if (!path_exists(tdir)) { if (!path_exists(tdir)) {
if (path_makepath(tdir, 0700)) { if (path_makepath(tdir, 0700)) {
LOGSYSERR("path_wingettempfilename", "path_makepath", tdir); 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); utf8towchar(tdir, dbuf, MAX_PATH);
wchar_t buf[MAX_PATH + 1]; wchar_t buf[MAX_PATH + 1];
GetTempFileNameW(dbuf, pref, 0, buf); static wchar_t prefix[]{L"rcl"};
string filename; GetTempFileNameW(dbuf, prefix, 0, buf);
wchartoutf8(buf, filename); wchartoutf8(buf, filename);
// Windows will have created a temp file, we delete it. // Windows will have created a temp file, we delete it.
if (!DeleteFileW(buf)) { if (!DeleteFileW(buf)) {
LOGSYSERR("path_wingettempfilename", "DeleteFileW", filename); LOGSYSERR("path_wingettempfilename", "DeleteFileW", filename);
@ -126,10 +139,35 @@ string path_wingettempfilename(wchar_t *pref)
LOGDEB1("path_wingettempfilename: DeleteFile " << filename << " Ok\n"); LOGDEB1("path_wingettempfilename: DeleteFile " << filename << " Ok\n");
} }
path_slashize(filename); 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. // Check if path is either non-existing or an empty directory.
bool path_empty(const string& path) 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 // There is a race condition between name computation and
// mkdir. try to make sure that we at least don't shoot ourselves // mkdir. try to make sure that we at least don't shoot ourselves
// in the foot // in the foot
#if !defined(HAVE_MKDTEMP) || defined(_WIN32) #if !defined(HAVE_MKDTEMP)
static std::mutex mmutex; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
#endif #endif
if (! if (!
#ifdef HAVE_MKDTEMP #ifdef HAVE_MKDTEMP
mkdtemp(cp) mkdtemp(cp)
#else #else
mktemp(cp) mktemp(cp)
#endif // HAVE_MKDTEMP #endif // HAVE_MKDTEMP
) { ) {
free(cp); free(cp);
reason = "maketmpdir: mktemp failed for [" + tdir + "] : " + reason = "maketmpdir: mktemp failed for [" + tdir + "] : " +
strerror(errno); strerror(errno);
tdir.erase(); tdir.erase();
return false; return false;
} }
@ -285,8 +323,9 @@ bool maketmpdir(string& tdir, string& reason)
// in the foot // in the foot
static std::mutex mmutex; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
static wchar_t tmpbasename[]{L"rcltmp"}; if (!path_gettempfilename(tdir, reason)) {
tdir = path_wingettempfilename(tmpbasename); return false;
}
#endif #endif
// At this point the directory does not exist yet except if we used // 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; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
#ifndef _WIN32 if (!path_gettempfilename(m_filename, m_reason)) {
string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
char *cp = strdup(filename.c_str());
if (!cp) {
m_reason = "Out of memory (for file name !)\n";
return; return;
} }
m_filename += suffix;
// 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;
LOGDEB1("TempFile: filename: " << m_filename << endl); LOGDEB1("TempFile: filename: " << m_filename << endl);
int fd1 = open(m_filename.c_str(), O_CREAT | O_EXCL, 0600); int fd1 = open(m_filename.c_str(), O_CREAT | O_EXCL, 0600);
if (fd1 < 0) { 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 #ifdef _WIN32
static list<string> remainingTempFileNames; static list<string> remainingTempFileNames;
static std::mutex remTmpFNMutex; static std::mutex remTmpFNMutex;
@ -423,8 +449,8 @@ TempFile::Internal::~Internal()
void TempFile::tryRemoveAgain() void TempFile::tryRemoveAgain()
{ {
#ifdef _WIN32 #ifdef _WIN32
LOGDEB1("TempFile::tryRemoveAgain. List size: " << LOGDEB1("TempFile::tryRemoveAgain. List size: " <<
remainingTempFileNames.size() << endl); remainingTempFileNames.size() << endl);
std::unique_lock<std::mutex> lock(remTmpFNMutex); std::unique_lock<std::mutex> lock(remTmpFNMutex);
std::list<string>::iterator pos = remainingTempFileNames.begin(); std::list<string>::iterator pos = remainingTempFileNames.begin();
while (pos != remainingTempFileNames.end()) { while (pos != remainingTempFileNames.end()) {

View File

@ -58,11 +58,15 @@ public:
const std::string& getreason() const; const std::string& getreason() const;
void setnoremove(bool onoff); void setnoremove(bool onoff);
bool ok() const; bool ok() const;
// Attempt to delete all files which could not be deleted on the // Attempt to delete all files which could not be deleted on the
// first try (typically on Windows: because they are open by some // first try (typically on Windows: because they are open by some
// process). Called after clearing the mimeHandler cache. Does // process). Called after clearing the mimeHandler cache. Does
// nothing if not _WIN32 // nothing if not _WIN32
static void tryRemoveAgain(); static void tryRemoveAgain();
// Also for Windows: for adding the temp files path to the default
// skippedPaths
static const std::string& rcltmpdir();
class Internal; class Internal;
private: private:
std::shared_ptr<Internal> m; std::shared_ptr<Internal> m;