diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 866e4dcc36..bf12159db8 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 c168ca5170..0598e87285 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 23acee0f9f..7628d0dfdb 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 8ec7474a0a..e428b5d76f 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 @@ -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 c95cacd606..2cc0369a63 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 @@ -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 fb6e822426..4dbcfd2675 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 bd819ab200..23fd1eed9a 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 #include @@ -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 96b71d81ea..0e10aaafca 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 @@ -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 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 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(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 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 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 22c129b350..f6c8433141 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 981420d3b5..514866ac49 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 4939874ab3..4d18ce0778 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 263c91eab9..e833a3570f 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 #include @@ -292,7 +293,9 @@ static void build_script(string const & from_file, // FIXME THREAD static int counter = 0; string const tmp = "gconvert" + convert(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 50c6e4be87..2e97fc0705 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 #include @@ -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 a875d37995..a6167b5dd9 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 949061017c..236b24ba85 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 #include @@ -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 08d726e0c6..84f13d6ae3 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 1b37ef2629..f0d1b54748 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 66d4b22701..b9c7e7f01a 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -37,6 +37,7 @@ #include "support/qstring_helpers.h" #include +#include #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