#include <config.h>
+#include "LyX.h"
#include "LyXRC.h"
#include "support/filetools.h"
+#include "support/convert.h"
#include "support/debug.h"
#include "support/environment.h"
#include "support/gettext.h"
#include "support/PathChanger.h"
#include "support/Systemcall.h"
#include "support/qstring_helpers.h"
+#include "support/TempFile.h"
#include <QDir>
-#include <QTemporaryFile>
#include "support/lassert.h"
#include "support/regex.h"
}
-static string createTempFile(QString const & mask)
+FileName const tempFileName(string const & mask, bool const dir)
{
- // FIXME: This is not safe. QTemporaryFile creates a file in open(),
- // but the file is deleted when qt_tmp goes out of scope.
- // Therefore the next call to createTempFile() may create the
- // same file again. To make this safe the QTemporaryFile object
- // needs to be kept for the whole life time of the temp file name.
- // This could be achieved by creating a class TempDir (like
- // TempFile, but using a currentlky non-existing
- // QTemporaryDirectory object).
- QTemporaryFile qt_tmp(mask + ".XXXXXXXXXXXX");
- if (qt_tmp.open()) {
- string const temp_file = fromqstr(qt_tmp.fileName());
- LYXERR(Debug::FILES, "Temporary file `" << temp_file << "' created.");
- return temp_file;
+ FileName tempfile = TempFile(mask).name();
+ // Since the QTemporaryFile object is destroyed at function return
+ // (which is what is intended here), the next call to this function
+ // may return the same file name again.
+ // Thus, in order to prevent race conditions, we track returned names
+ // and create our own unique names if QTemporaryFile returns a name again.
+ if (tmp_names_.find(tempfile.absFileName()) == tmp_names_.end()) {
+ tmp_names_.insert(tempfile.absFileName());
+ return tempfile;
}
- LYXERR(Debug::FILES, "Unable to create temporary file with following template: "
- << qt_tmp.fileTemplate());
- return string();
+
+ // OK, we need another name. Simply append digits.
+ FileName tmp = tempfile;
+ string ext;
+ if (!dir) {
+ // Store and remove extensions
+ ext = "." + tempfile.extension();
+ tmp.changeExtension("");
+ }
+ for (int i = 1; i < INT_MAX ;++i) {
+ // Append digit to filename and re-add extension
+ string const new_fn =
+ tmp.absFileName() + convert<string>(i) + ext;
+ if (tmp_names_.find(new_fn) == tmp_names_.end()) {
+ tmp_names_.insert(new_fn);
+ tempfile.set(new_fn);
+ return tempfile;
+ }
+ }
+
+ // This should not happen!
+ LYXERR0("tempFileName(): Could not create unique temp file name!");
+ return tempfile;
+}
+
+
+void removeTempFile(FileName const & fn)
+{
+ if (!fn.exists())
+ return;
+
+ string const abs = fn.absFileName();
+ if (tmp_names_.find(abs) != tmp_names_.end())
+ tmp_names_.erase(abs);
+ fn.removeFile();
}
<< "createTmpDir: mask=`" << mask << '\'');
QFileInfo tmp_fi(QDir(toqstr(tempdir.absFileName())), toqstr(mask));
- FileName const tmpfl(createTempFile(tmp_fi.absoluteFilePath()));
+ FileName const tmpfl =
+ tempFileName(fromqstr(tmp_fi.absoluteFilePath()) + ".XXXXXXXXXXXX", true);
if (tmpfl.empty() || !tmpfl.createDirectory(0700)) {
LYXERR0("LyX could not create temporary directory in " << tempdir
// $[A-Za-z_][A-Za-z_0-9]*
static string const envvar = "[$]([A-Za-z_][A-Za-z_0-9]*)";
- static regex const envvar_br_re("(.*)" + envvar_br + "(.*)");
- static regex const envvar_re("(.*)" + envvar + "(.*)");
- string result = path;
- while (1) {
- smatch what;
- if (!regex_match(result, what, envvar_br_re)) {
- if (!regex_match(result, what, envvar_re))
- break;
+ // Coverity thinks that the regex constructor can return an
+ // exception. We know that it is not true since our regex are
+ // hardcoded, but we have to protect against that nevertheless.
+ try {
+ static regex const envvar_br_re("(.*)" + envvar_br + "(.*)");
+ static regex const envvar_re("(.*)" + envvar + "(.*)");
+ string result = path;
+ while (1) {
+ smatch what;
+ if (!regex_match(result, what, envvar_br_re)) {
+ if (!regex_match(result, what, envvar_re))
+ break;
+ }
+ string env_var = getEnv(what.str(2));
+ result = what.str(1) + env_var + what.str(3);
}
- string env_var = getEnv(what.str(2));
- result = what.str(1) + env_var + what.str(3);
+ return result;
+ } catch (exception const & e) {
+ LYXERR0("Something is very wrong: " << e.what());
+ return path;
}
- return result;
}
// pstream (process stream), with the
// variants ipstream, opstream
+ if (verbose)
+ lyxerr << "\nRunning: " << cmd << endl;
+ else
+ LYXERR(Debug::INFO,"Running: " << cmd);
+
#if defined (_WIN32)
STARTUPINFO startup;
PROCESS_INFORMATION process;
#if defined (_WIN32)
WaitForSingleObject(process.hProcess, INFINITE);
+ DWORD pret;
+ if (!GetExitCodeProcess(process.hProcess, &pret))
+ pret = -1;
if (!infile.empty())
CloseHandle(startup.hStdInput);
CloseHandle(process.hProcess);
- int const pret = fclose(inf);
+ if (fclose(inf) != 0)
+ pret = -1;
#elif defined (HAVE_PCLOSE)
int const pret = pclose(inf);
#elif defined (HAVE__PCLOSE)
}
-FileName const findtexfile(string const & fil, string const & /*format*/)
+FileName const findtexfile(string const & fil, string const & /*format*/,
+ bool const onlykpse)
{
/* There is no problem to extend this function too use other
methods to look for files. It could be setup to look
// If the file can be found directly, we just return a
// absolute path version of it.
- FileName const absfile(makeAbsPath(fil));
- if (absfile.exists())
- return absfile;
+ if (!onlykpse) {
+ FileName const absfile(makeAbsPath(fil));
+ if (absfile.exists())
+ return absfile;
+ }
// Now we try to find it using kpsewhich.
// It seems from the kpsewhich manual page that it is safe to use