commit f09a9fe2e60e4aeaca23b42b2bf30f5d64cfd9b1
Author: Georg Baum <[email protected]>
Date: Mon Jun 9 13:05:50 2014 +0200
Remove unsafe method FileName::tempName()
FileName::tempName() created a new temp file name by using qt to create a
temporary file with a unique name, and then deleting that file and returning
the name. This was unsafe, since other processes or even other threads of
the
running LyX could create files with the same name between deletion and then
using the temp name.
This is fixed by using the TempFile class instead. As a side effect, a few
cases where the temp files were not deleted after usage were fixed as well.
The only place that is still unsafe is createTmpDir().
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 866e4dc..bf12159 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -1050,7 +1050,8 @@ bool Buffer::readString(string const & s)
Lexer lex;
istringstream is(s);
lex.setStream(is);
- FileName const fn = FileName::tempName("Buffer_readString");
+ TempFile tempfile("Buffer_readStringXXXXXX.lyx");
+ FileName const fn = tempfile.name();
int file_format;
bool success = parseLyXFormat(lex, fn, file_format) == ReadSuccess;
@@ -1067,8 +1068,6 @@ bool Buffer::readString(string const & s)
else if (success)
if (readDocument(lex))
success = false;
- if (fn.exists())
- fn.removeFile();
return success;
}
@@ -1189,7 +1188,9 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex,
Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
FileName & tmpfile, int from_format)
{
- tmpfile = FileName::tempName("Buffer_convertLyXFormatXXXXXX.lyx");
+ TempFile tempfile("Buffer_convertLyXFormatXXXXXX.lyx");
+ tempfile.setAutoRemove(false);
+ tmpfile = tempfile.name();
if(tmpfile.empty()) {
Alert::error(_("Conversion failed"),
bformat(_("%1$s is from a different"
@@ -3730,7 +3731,9 @@ int AutoSaveBuffer::generateChild()
// to fork. But we will do the save
// anyway.
bool failed = false;
- FileName const tmp_ret = FileName::tempName("lyxauto");
+ TempFile tempfile("lyxautoXXXXXX.lyx");
+ tempfile.setAutoRemove(false);
+ FileName const tmp_ret = tempfile.name();
if (!tmp_ret.empty()) {
buffer_.writeFile(tmp_ret);
// assume successful write of tmp_ret
@@ -3814,7 +3817,9 @@ bool Buffer::autoSave() const
// If this buffer is cloned, we assume that
// we are running in a separate thread already.
- FileName const tmp_ret = FileName::tempName("lyxauto");
+ TempFile tempfile("lyxautoXXXXXX.lyx");
+ tempfile.setAutoRemove(false);
+ FileName const tmp_ret = tempfile.name();
if (!tmp_ret.empty()) {
writeFile(tmp_ret);
// assume successful write of tmp_ret
diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp
index c168ca5..0598e87 100644
--- a/src/CutAndPaste.cpp
+++ b/src/CutAndPaste.cpp
@@ -60,6 +60,7 @@
#include "support/lassert.h"
#include "support/limited_stack.h"
#include "support/lstrings.h"
+#include "support/TempFile.h"
#include "frontends/alert.h"
#include "frontends/Clipboard.h"
@@ -484,8 +485,10 @@ void putClipboard(ParagraphList const & paragraphs,
// new temporary directory, etc) every time, and then to destroy it. So
maybe
// it's worth just keeping this one around.
// FIXME THREAD
+ static TempFile tempfile("clipboard.internal");
+ tempfile.setAutoRemove(false);
static Buffer * staticbuffer = theBufferList().newInternalBuffer(
- FileName::tempName("clipboard.internal").absFileName());
+ tempfile.name().absFileName());
// These two things only really need doing the first time.
staticbuffer->setUnnamed(true);
diff --git a/src/KeyMap.cpp b/src/KeyMap.cpp
index 23acee0..7628d0d 100644
--- a/src/KeyMap.cpp
+++ b/src/KeyMap.cpp
@@ -25,6 +25,7 @@
#include "support/filetools.h"
#include "support/gettext.h"
#include "support/lstrings.h"
+#include "support/TempFile.h"
#include "frontends/alert.h"
@@ -254,7 +255,8 @@ bool KeyMap::read(FileName const & bind_file, KeyMap *
unbind_map)
return retval == ReadOK;
LYXERR(Debug::FILES, "Converting bind file to " << LFUN_FORMAT);
- FileName const tempfile = FileName::tempName("convert_bind");
+ TempFile tmp("convert_bind");
+ FileName const tempfile = tmp.name();
bool const success = prefs2prefs(bind_file, tempfile, true);
if (!success) {
LYXERR0 ("Unable to convert " << bind_file <<
@@ -262,7 +264,6 @@ bool KeyMap::read(FileName const & bind_file, KeyMap *
unbind_map)
return false;
}
retval = readWithoutConv(tempfile, unbind_map);
- tempfile.removeFile();
return retval == ReadOK;
}
diff --git a/src/LayoutFile.cpp b/src/LayoutFile.cpp
index 8ec7474..e428b5d 100644
--- a/src/LayoutFile.cpp
+++ b/src/LayoutFile.cpp
@@ -29,6 +29,7 @@
#include "support/bind.h"
#include "support/regex.h"
+#include "support/TempFile.h"
#include <fstream>
@@ -224,8 +225,9 @@ string layoutpost =
LayoutFileIndex LayoutFileList::addEmptyClass(string const & textclass)
{
// FIXME This could be simplified a bit to call TextClass::read(string,
ReadType).
-
- FileName const tempLayout = FileName::tempName("basic_layout");
+
+ TempFile tempfile("basicXXXXXX.layout");
+ FileName const tempLayout = tempfile.name();
ofstream ofs(tempLayout.toFilesystemEncoding().c_str());
// This writes a very basic class, but it also attempts to include
// stdclass.inc. That would give us something moderately usable.
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index c95cacd..2cc0369 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -40,6 +40,7 @@
#include "support/lstrings.h"
#include "support/os.h"
#include "support/Package.h"
+#include "support/TempFile.h"
#include "support/userinfo.h"
#include <fstream>
@@ -407,7 +408,8 @@ bool LyXRC::read(FileName const & filename, bool
check_format)
return retval == ReadOK;
LYXERR(Debug::FILES, "Converting LyXRC file to " << LYXRC_FILEFORMAT);
- FileName const tempfile = FileName::tempName("convert_lyxrc");
+ TempFile tmp("convert_lyxrc");
+ FileName const tempfile = tmp.name();
bool const success = prefs2prefs(filename, tempfile, false);
if (!success) {
LYXERR0 ("Unable to convert " << filename.absFileName() <<
@@ -422,7 +424,6 @@ bool LyXRC::read(FileName const & filename, bool
check_format)
LYXERR(Debug::LYXRC, "Reading '" << tempfile << "'...");
retval = read(lexrc2, check_format);
}
- tempfile.removeFile();
return retval == ReadOK;
}
diff --git a/src/LyXVC.cpp b/src/LyXVC.cpp
index fb6e822..4dbcfd2 100644
--- a/src/LyXVC.cpp
+++ b/src/LyXVC.cpp
@@ -25,6 +25,7 @@
#include "support/filetools.h"
#include "support/gettext.h"
#include "support/lstrings.h"
+#include "support/TempFile.h"
using namespace std;
using namespace lyx::support;
@@ -362,7 +363,9 @@ string const LyXVC::getLogFile() const
if (!vcs)
return string();
- FileName const tmpf = FileName::tempName("lyxvclog");
+ TempFile tempfile("lyxvclog");
+ tempfile.setAutoRemove(false);
+ FileName const tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return string();
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index bd819ab..23fd1ee 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -36,6 +36,7 @@
#include "support/gettext.h"
#include "support/lstrings.h"
#include "support/os.h"
+#include "support/TempFile.h"
#include <algorithm>
#include <fstream>
@@ -278,22 +279,24 @@ LexerKeyword textClassTags[] = {
bool TextClass::convertLayoutFormat(support::FileName const & filename,
ReadType rt)
{
LYXERR(Debug::TCLASS, "Converting layout file to " << LAYOUT_FORMAT);
- FileName const tempfile = FileName::tempName("convert_layout");
+ TempFile tmp("convertXXXXXX.layout");
+ FileName const tempfile = tmp.name();
bool success = layout2layout(filename, tempfile);
if (success)
success = readWithoutConv(tempfile, rt) == OK;
- tempfile.removeFile();
return success;
}
std::string TextClass::convert(std::string const & str)
{
- FileName const fn = FileName::tempName("locallayout");
+ TempFile tmp1("localXXXXXX.layout");
+ FileName const fn = tmp1.name();
ofstream os(fn.toFilesystemEncoding().c_str());
os << str;
os.close();
- FileName const tempfile = FileName::tempName("convert_locallayout");
+ TempFile tmp2("convert_localXXXXXX.layout");
+ FileName const tempfile = tmp2.name();
bool success = layout2layout(fn, tempfile);
if (!success)
return "";
@@ -305,7 +308,6 @@ std::string TextClass::convert(std::string const & str)
ret += tmp + '\n';
}
is.close();
- tempfile.removeFile();
return ret;
}
@@ -370,7 +372,8 @@ TextClass::ReturnValues TextClass::read(std::string const &
str, ReadType rt)
return retval;
// write the layout string to a temporary file
- FileName const tempfile = FileName::tempName("TextClass_read");
+ TempFile tmp("TextClass_read");
+ FileName const tempfile = tmp.name();
ofstream os(tempfile.toFilesystemEncoding().c_str());
if (!os) {
LYXERR0("Unable to create temporary file");
@@ -386,7 +389,6 @@ TextClass::ReturnValues TextClass::read(std::string const &
str, ReadType rt)
<< LAYOUT_FORMAT);
return ERROR;
}
- tempfile.removeFile();
return OK_OLDFORMAT;
}
diff --git a/src/VCBackend.cpp b/src/VCBackend.cpp
index 96b71d8..0e10aaa 100644
--- a/src/VCBackend.cpp
+++ b/src/VCBackend.cpp
@@ -27,6 +27,7 @@
#include "support/PathChanger.h"
#include "support/Systemcall.h"
#include "support/regex.h"
+#include "support/TempFile.h"
#include <fstream>
@@ -292,7 +293,8 @@ bool RCS::isCheckInWithConfirmation()
// if (getDiff(file, diff) && diff.empty())
// return false;
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return true;
@@ -303,7 +305,6 @@ bool RCS::isCheckInWithConfirmation()
FileName(owner_->filePath()));
docstring diff = tmpf.fileContents("UTF-8");
- tmpf.removeFile();
if (diff.empty())
return false;
@@ -433,7 +434,8 @@ string RCS::revisionInfo(LyXVC::RevisionInfo const info)
bool RCS::getRevisionInfo()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -480,7 +482,9 @@ bool RCS::prepareFileRevision(string const &revis, string &
f)
if (!VCS::makeRCSRevision(version_, rev))
return false;
- FileName tmpf = FileName::tempName("lyxvcrev_" + rev + "_");
+ TempFile tempfile("lyxvcrev_" + rev + "_");
+ tempfile.setAutoRemove(false);
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -657,7 +661,8 @@ int CVS::doVCCommandCallWithOutput(std::string const & cmd,
CVS::CvsStatus CVS::getStatus()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return StatusError;
@@ -665,7 +670,6 @@ CVS::CvsStatus CVS::getStatus()
if (doVCCommandCallWithOutput("cvs status " + getTarget(File),
FileName(owner_->filePath()), tmpf)) {
- tmpf.removeFile();
return StatusError;
}
@@ -689,7 +693,6 @@ CVS::CvsStatus CVS::getStatus()
status = NeedsCheckout;
}
}
- tmpf.removeFile();
return status;
}
@@ -698,7 +701,8 @@ void CVS::getRevisionInfo()
if (have_rev_info_)
return;
have_rev_info_ = true;
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return;
@@ -708,7 +712,6 @@ void CVS::getRevisionInfo()
+ " " + getTarget(File),
FileName(owner_->filePath()), tmpf);
if (rc) {
- tmpf.removeFile();
LYXERR(Debug::LYXVC, "cvs log failed with exit code " << rc);
return;
}
@@ -731,7 +734,6 @@ void CVS::getRevisionInfo()
break;
}
}
- tmpf.removeFile();
if (rev_author_cache_.empty())
LYXERR(Debug::LYXVC,
"Could not retrieve revision info for " << version_ <<
@@ -902,7 +904,8 @@ string CVS::checkOut()
{
if (vcstatus != NOLOCKING && edit())
return string();
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return string();
@@ -920,7 +923,6 @@ string CVS::checkOut()
rc = 0;
}
- tmpf.removeFile();
return rc ? string() : log.empty() ? "CVS: Proceeded" : "CVS: " + log;
}
@@ -936,7 +938,8 @@ bool CVS::checkOutEnabled()
string CVS::repoUpdate()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return string();
@@ -959,10 +962,8 @@ string CVS::repoUpdate()
text, 0, 1, _("&Continue"), _("&Abort"));
hideDialogs("file", 0);
}
- if (ret == 1 ) {
- tmpf.removeFile();
+ if (ret == 1 )
return string();
- }
}
int rc = update(Directory, tmpf);
@@ -980,8 +981,6 @@ string CVS::repoUpdate()
file, from_local8bit(sres)));
rc = 0;
}
-
- tmpf.removeFile();
return rc ? string() : log.empty() ? "CVS: Proceeded" : "CVS: " + log;
}
@@ -1108,7 +1107,9 @@ bool CVS::prepareFileRevision(string const & revis,
string & f)
if (!VCS::makeRCSRevision(version_, rev))
return false;
- FileName tmpf = FileName::tempName("lyxvcrev_" + rev + "_");
+ TempFile tempfile("lyxvcrev_" + rev + "_");
+ tempfile.setAutoRemove(false);
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -1156,7 +1157,8 @@ FileName const SVN::findFile(FileName const & file)
}
// Now we check the status of the file.
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return FileName();
@@ -1167,7 +1169,6 @@ FileName const SVN::findFile(FileName const & file)
bool found = 0 == doVCCommandCall("svn info " + quoteName(fname)
+ " > " +
quoteName(tmpf.toFilesystemEncoding()),
file.onlyPath());
- tmpf.removeFile();
LYXERR(Debug::LYXVC, "SVN control: " << (found ? "enabled" :
"disabled"));
return found ? file : FileName();
}
@@ -1189,7 +1190,8 @@ void SVN::scanMaster()
bool SVN::checkLockMode()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()){
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -1319,7 +1321,8 @@ LyXVC::CommandResult SVN::checkIn(string const & msg,
string & log)
LyXVC::CommandResult
SVN::checkIn(vector<support::FileName> const & f, string const & msg, string &
log)
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()){
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
log = N_("Error: Could not generate logfile.");
@@ -1347,7 +1350,6 @@ SVN::checkIn(vector<support::FileName> const & f, string
const & msg, string & l
if (!fileLock(false, tmpf, log))
ret = LyXVC::ErrorCommand;
- tmpf.removeFile();
if (!log.empty())
log.insert(0, "SVN: ");
if (ret == LyXVC::VCSuccess && log.empty())
@@ -1369,7 +1371,8 @@ bool SVN::isCheckInWithConfirmation()
{
// FIXME one day common getDiff and perhaps OpMode for all backends
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return true;
@@ -1380,7 +1383,6 @@ bool SVN::isCheckInWithConfirmation()
FileName(owner_->filePath()));
docstring diff = tmpf.fileContents("UTF-8");
- tmpf.removeFile();
if (diff.empty())
return false;
@@ -1455,7 +1457,8 @@ bool SVN::fileLock(bool lock, FileName const & tmpf,
string &status)
string SVN::checkOut()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return N_("Error: Could not generate logfile.");
@@ -1476,7 +1479,6 @@ string SVN::checkOut()
fileLock(true, tmpf, log);
- tmpf.removeFile();
return log.empty() ? string() : "SVN: " + log;
}
@@ -1492,7 +1494,8 @@ bool SVN::checkOutEnabled()
string SVN::repoUpdate()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return N_("Error: Could not generate logfile.");
@@ -1518,10 +1521,8 @@ string SVN::repoUpdate()
text, 0, 1, _("&Yes"), _("&No"));
hideDialogs("file", 0);
}
- if (ret == 1 ) {
- tmpf.removeFile();
+ if (ret == 1 )
return string();
- }
}
// Reverting looks too harsh, see bug #6255.
@@ -1535,7 +1536,6 @@ string SVN::repoUpdate()
res += "Update log:\n" + tmpf.fileContents("UTF-8");
LYXERR(Debug::LYXVC, res);
- tmpf.removeFile();
return to_utf8(res);
}
@@ -1548,7 +1548,8 @@ bool SVN::repoUpdateEnabled()
string SVN::lockingToggle()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return N_("Error: Could not generate logfile.");
@@ -1576,7 +1577,6 @@ string SVN::lockingToggle()
if (ret)
return string();
- tmpf.removeFile();
frontend::Alert::warning(_("SVN File Locking"),
(locking ? _("Locking property unset.") : _("Locking property
set.")) + "\n"
+ _("Do not forget to commit the locking property into the
repository."),
@@ -1667,7 +1667,8 @@ string SVN::revisionInfo(LyXVC::RevisionInfo const info)
bool SVN::getFileRevisionInfo()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -1713,14 +1714,14 @@ bool SVN::getFileRevisionInfo()
}
ifs.close();
- tmpf.removeFile();
return !rev.empty();
}
bool SVN::getTreeRevisionInfo()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -1737,7 +1738,6 @@ bool SVN::getTreeRevisionInfo()
string line;
getline(ifs, line);
ifs.close();
- tmpf.removeFile();
rev_tree_cache_ = line;
return !line.empty();
@@ -1771,7 +1771,9 @@ bool SVN::prepareFileRevision(string const & revis,
string & f)
}
string revname = convert<string>(rev);
- FileName tmpf = FileName::tempName("lyxvcrev_" + revname + "_");
+ TempFile tempfile("lyxvcrev_" + revname + "_");
+ tempfile.setAutoRemove(false);
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -1826,7 +1828,8 @@ FileName const GIT::findFile(FileName const & file)
}
// Now we check the status of the file.
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return FileName();
@@ -1840,7 +1843,6 @@ FileName const GIT::findFile(FileName const & file)
quoteName(tmpf.toFilesystemEncoding()),
file.onlyPath());
bool found = !tmpf.isFileEmpty();
- tmpf.removeFile();
LYXERR(Debug::LYXVC, "GIT control: " << (found ? "enabled" :
"disabled"));
return found ? file : FileName();
}
@@ -1934,7 +1936,8 @@ LyXVC::CommandResult GIT::checkIn(string const & msg,
string & log)
LyXVC::CommandResult
GIT::checkIn(vector<support::FileName> const & f, string const & msg, string &
log)
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()){
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
log = N_("Error: Could not generate logfile.");
@@ -1959,7 +1962,6 @@ GIT::checkIn(vector<support::FileName> const & f, string
const & msg, string & l
ret = LyXVC::ErrorCommand;
}
- tmpf.removeFile();
if (!log.empty())
log.insert(0, "GIT: ");
if (ret == LyXVC::VCSuccess && log.empty())
@@ -1978,7 +1980,8 @@ bool GIT::isCheckInWithConfirmation()
{
// FIXME one day common getDiff and perhaps OpMode for all backends
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return true;
@@ -1989,7 +1992,6 @@ bool GIT::isCheckInWithConfirmation()
FileName(owner_->filePath()));
docstring diff = tmpf.fileContents("UTF-8");
- tmpf.removeFile();
if (diff.empty())
return false;
@@ -2132,7 +2134,8 @@ string GIT::revisionInfo(LyXVC::RevisionInfo const info)
bool GIT::getFileRevisionInfo()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -2158,14 +2161,14 @@ bool GIT::getFileRevisionInfo()
}
ifs.close();
- tmpf.removeFile();
return !rev_file_cache_.empty();
}
bool GIT::getTreeRevisionInfo()
{
- FileName tmpf = FileName::tempName("lyxvcout");
+ TempFile tempfile("lyxvcout");
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
@@ -2181,7 +2184,6 @@ bool GIT::getTreeRevisionInfo()
ifstream ifs(tmpf.toFilesystemEncoding().c_str());
getline(ifs, rev_tree_cache_);
ifs.close();
- tmpf.removeFile();
return !rev_tree_cache_.empty();
}
@@ -2218,7 +2220,9 @@ bool GIT::prepareFileRevision(string const & revis,
string & f)
pointer += ":";
- FileName tmpf = FileName::tempName("lyxvcrev_" + revis + "_");
+ TempFile tempfile("lyxvcrev_" + revis + "_");
+ tempfile.setAutoRemove(false);
+ FileName tmpf = tempfile.name();
if (tmpf.empty()) {
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return false;
diff --git a/src/frontends/qt4/GuiApplication.cpp
b/src/frontends/qt4/GuiApplication.cpp
index 22c129b..f6c8433 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -70,6 +70,7 @@
#include "support/Package.h"
#include "support/PathChanger.h"
#include "support/Systemcall.h"
+#include "support/TempFile.h"
#ifdef Q_WS_MACX
#include "support/AppleScript.h"
@@ -2827,14 +2828,14 @@ bool GuiApplication::readUIFile(QString const & name,
bool include)
if (retval == FormatMismatch) {
LYXERR(Debug::FILES, "Converting ui file to format " <<
LFUN_FORMAT);
- FileName const tempfile = FileName::tempName("convert_ui");
+ TempFile tmp("convertXXXXXX.ui");
+ FileName const tempfile = tmp.name();
bool const success = prefs2prefs(ui_path, tempfile, true);
if (!success) {
LYXERR0("Unable to convert " << ui_path.absFileName() <<
" to format " << LFUN_FORMAT << ".");
} else {
retval = readUIFile(tempfile);
- tempfile.removeFile();
}
}
diff --git a/src/frontends/qt4/GuiWorkArea.cpp
b/src/frontends/qt4/GuiWorkArea.cpp
index 981420d..514866a 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -49,6 +49,7 @@
#include "support/gettext.h"
#include "support/FileName.h"
#include "support/lassert.h"
+#include "support/TempFile.h"
#include "frontends/Application.h"
#include "frontends/FontMetrics.h"
@@ -1426,8 +1427,9 @@ GuiView & GuiWorkArea::view()
EmbeddedWorkArea::EmbeddedWorkArea(QWidget * w): GuiWorkArea(w)
{
- buffer_ = theBufferList().newInternalBuffer(
- support::FileName::tempName("embedded.internal").absFileName());
+ support::TempFile tempfile("embedded.internal");
+ tempfile.setAutoRemove(false);
+ buffer_ =
theBufferList().newInternalBuffer(tempfile.name().absFileName());
buffer_->setUnnamed(true);
buffer_->setFullyLoaded(true);
setBuffer(*buffer_);
diff --git a/src/graphics/GraphicsCacheItem.cpp
b/src/graphics/GraphicsCacheItem.cpp
index 4939874..4d18ce0 100644
--- a/src/graphics/GraphicsCacheItem.cpp
+++ b/src/graphics/GraphicsCacheItem.cpp
@@ -28,6 +28,7 @@
#include "support/lassert.h"
#include "support/bind.h"
+#include "support/TempFile.h"
using namespace std;
using namespace lyx::support;
@@ -361,8 +362,9 @@ bool CacheItem::Impl::tryDisplayFormat(FileName & filename,
string & from)
zipped_ = formats.isZippedFile(filename_);
if (zipped_) {
- unzipped_filename_ = FileName::tempName(
- filename_.toFilesystemEncoding());
+ TempFile tempfile(filename_.toFilesystemEncoding());
+ tempfile.setAutoRemove(false);
+ unzipped_filename_ = tempfile.name();
if (unzipped_filename_.empty()) {
status_ = ErrorConverting;
LYXERR(Debug::GRAPHICS, "\tCould not create temporary
file.");
@@ -422,7 +424,9 @@ void CacheItem::Impl::convertToDisplayFormat()
// Add some stuff to create a uniquely named temporary file.
// This file is deleted in loadImage after it is loaded into memory.
- FileName const to_file_base = FileName::tempName("CacheItem");
+ TempFile tempfile("CacheItem");
+ tempfile.setAutoRemove(false);
+ FileName const to_file_base = tempfile.name();
remove_loaded_file_ = true;
// Connect a signal to this->imageConverted and pass this signal to
diff --git a/src/graphics/GraphicsConverter.cpp
b/src/graphics/GraphicsConverter.cpp
index 263c91e..e833a35 100644
--- a/src/graphics/GraphicsConverter.cpp
+++ b/src/graphics/GraphicsConverter.cpp
@@ -25,6 +25,7 @@
#include "support/os.h"
#include "support/bind.h"
+#include "support/TempFile.h"
#include <sstream>
#include <fstream>
@@ -292,7 +293,9 @@ static void build_script(string const & from_file,
// FIXME THREAD
static int counter = 0;
string const tmp = "gconvert" + convert<string>(counter++);
- string const to_base = FileName::tempName(tmp).toFilesystemEncoding();
+ TempFile tempfile(tmp);
+ tempfile.setAutoRemove(false);
+ string const to_base = tempfile.name().toFilesystemEncoding();
// Create a copy of the file in case the original name contains
// problematic characters like ' or ". We can work around that problem
@@ -366,7 +369,9 @@ static void build_script(string const & from_file,
// If two formats share the same extension we may get identical
names
if (outfile == infile && conv.result_file.empty()) {
- string const new_base =
FileName::tempName(tmp).toFilesystemEncoding();
+ TempFile tempfile(tmp);
+ tempfile.setAutoRemove(false);
+ string const new_base =
tempfile.name().toFilesystemEncoding();
outfile = addExtension(new_base, conv.To->extension());
}
diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp
index 50c6e4b..2e97fc0 100644
--- a/src/insets/InsetExternal.cpp
+++ b/src/insets/InsetExternal.cpp
@@ -45,6 +45,7 @@
#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/lyxlib.h"
+#include "support/TempFile.h"
#include <sstream>
#include <vector>
@@ -67,33 +68,39 @@ namespace Alert = frontend::Alert;
namespace external {
-TempName::TempName()
+TempName::TempName() : tempfile_(new support::TempFile("lyxextXXXXXX.tmp"))
{
- FileName const tempname = FileName::tempName("lyxext");
// must have an extension for the converter code to work correctly.
- tempname_ = FileName(tempname.absFileName() + ".tmp");
}
-TempName::TempName(TempName const &)
+TempName::TempName(TempName const & that) : tempfile_(0)
{
- tempname_ = TempName()();
+ *this = that;
}
TempName::~TempName()
{
- tempname_.removeFile();
+ delete tempfile_;
}
TempName & TempName::operator=(TempName const & other)
{
- if (this != &other)
- tempname_ = TempName()();
+ if (this != &other) {
+ delete tempfile_;
+ tempfile_ = new support::TempFile("lyxextXXXXXX.tmp");
+ }
return *this;
}
+
+support::FileName TempName::operator()() const
+{
+ return tempfile_->name();
+}
+
} // namespace external
diff --git a/src/insets/InsetExternal.h b/src/insets/InsetExternal.h
index a875d37..a6167b5 100644
--- a/src/insets/InsetExternal.h
+++ b/src/insets/InsetExternal.h
@@ -31,6 +31,10 @@
*/
namespace lyx {
+namespace support {
+class TempFile;
+}
+
namespace external {
class TempName {
@@ -39,9 +43,9 @@ public:
TempName(TempName const &);
~TempName();
TempName & operator=(TempName const &);
- support::FileName const & operator()() const { return tempname_; }
+ support::FileName operator()() const;
private:
- support::FileName tempname_;
+ support::TempFile * tempfile_;
};
} // namespace external
@@ -56,7 +60,7 @@ public:
bool read(Buffer const &, Lexer &);
/// The name of the tempfile used for manipulations.
- support::FileName const & tempname() const { return tempname_(); }
+ support::FileName tempname() const { return tempname_(); }
/// The template currently in use.
void settemplate(std::string const &);
diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp
index 9490610..236b24b 100644
--- a/src/mathed/MathExtern.cpp
+++ b/src/mathed/MathExtern.cpp
@@ -40,6 +40,7 @@
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/lstrings.h"
+#include "support/TempFile.h"
#include <algorithm>
#include <sstream>
@@ -995,7 +996,8 @@ namespace {
{
// In order to avoid parsing problems with command interpreters
// we pass input data through a file
- FileName const cas_tmpfile = FileName::tempName("casinput");
+ TempFile tempfile("casinput");
+ FileName const cas_tmpfile = tempfile.name();
if (cas_tmpfile.empty()) {
lyxerr << "Warning: cannot create temporary file."
<< endl;
@@ -1009,7 +1011,6 @@ namespace {
lyxerr << "calling: " << cmd
<< "\ninput: '" << data << "'" << endl;
cmd_ret const ret = runCommand(command);
- cas_tmpfile.removeFile();
return ret.second;
}
diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp
index 08d726e..84f13d6 100644
--- a/src/support/FileName.cpp
+++ b/src/support/FileName.cpp
@@ -454,40 +454,6 @@ FileNameList FileName::dirList(string const & ext) const
}
-static string createTempFile(QString const & mask)
-{
- // 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 can be achieved by using the TempFile class.
- 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;
- }
- LYXERR(Debug::FILES, "Unable to create temporary file with following
template: "
- << qt_tmp.fileTemplate());
- return string();
-}
-
-
-FileName FileName::tempName(FileName const & temp_dir, string const & mask)
-{
- QFileInfo tmp_fi(QDir(temp_dir.d->fi.absoluteFilePath()), toqstr(mask));
- LYXERR(Debug::FILES, "Temporary file in " << tmp_fi.absoluteFilePath());
- return FileName(createTempFile(tmp_fi.absoluteFilePath()));
-}
-
-
-FileName FileName::tempName(string const & mask)
-{
- return tempName(package().temp_dir(), mask);
-}
-
-
FileName FileName::getcwd()
{
// return makeAbsPath("."); would create an infinite loop
diff --git a/src/support/FileName.h b/src/support/FileName.h
index 1b37ef2..f0d1b54 100644
--- a/src/support/FileName.h
+++ b/src/support/FileName.h
@@ -175,15 +175,6 @@ public:
void changeExtension(std::string const & extension);
static FileName fromFilesystemEncoding(std::string const & name);
- /// Create a temporary file with the given mask.
- /// \p mask must be in filesystem encoding, if it contains a
- /// relative path, the template file will be created in the global
- /// temporary directory as given by 'package().temp_dir()'.
- /// CAUTION: This method may create race conditions.
- /// Do not use, use the TempFile class instead.
- static FileName tempName(std::string const & mask);
- static FileName tempName(FileName const & temp_dir,
- std::string const & mask);
/// get the current working directory
static FileName getcwd();
diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp
index 66d4b22..b9c7e7f 100644
--- a/src/support/filetools.cpp
+++ b/src/support/filetools.cpp
@@ -37,6 +37,7 @@
#include "support/qstring_helpers.h"
#include <QDir>
+#include <QTemporaryFile>
#include "support/lassert.h"
#include "support/regex.h"
@@ -378,12 +379,35 @@ string const commandPrep(string const & command_in)
}
+static string createTempFile(QString const & mask)
+{
+ // 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;
+ }
+ LYXERR(Debug::FILES, "Unable to create temporary file with following
template: "
+ << qt_tmp.fileTemplate());
+ return string();
+}
+
+
static FileName createTmpDir(FileName const & tempdir, string const & mask)
{
LYXERR(Debug::FILES, "createTmpDir: tempdir=`" << tempdir << "'\n"
<< "createTmpDir: mask=`" << mask << '\'');
- FileName const tmpfl = FileName::tempName(tempdir, mask);
+ QFileInfo tmp_fi(QDir(toqstr(tempdir.absFileName())), toqstr(mask));
+ FileName const tmpfl(createTempFile(tmp_fi.absoluteFilePath()));
if (tmpfl.empty() || !tmpfl.createDirectory(0700)) {
LYXERR0("LyX could not create temporary directory in " <<
tempdir