]> git.lyx.org Git - features.git/commitdiff
Remove unsafe method FileName::tempName()
authorGeorg Baum <baum@lyx.org>
Mon, 9 Jun 2014 11:05:50 +0000 (13:05 +0200)
committerGeorg Baum <baum@lyx.org>
Mon, 9 Jun 2014 11:05:50 +0000 (13:05 +0200)
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().

18 files changed:
src/Buffer.cpp
src/CutAndPaste.cpp
src/KeyMap.cpp
src/LayoutFile.cpp
src/LyXRC.cpp
src/LyXVC.cpp
src/TextClass.cpp
src/VCBackend.cpp
src/frontends/qt4/GuiApplication.cpp
src/frontends/qt4/GuiWorkArea.cpp
src/graphics/GraphicsCacheItem.cpp
src/graphics/GraphicsConverter.cpp
src/insets/InsetExternal.cpp
src/insets/InsetExternal.h
src/mathed/MathExtern.cpp
src/support/FileName.cpp
src/support/FileName.h
src/support/filetools.cpp

index 866e4dcc3658c601750f327d684c3d48b63a29dd..bf12159db8f1f76ac9b45438f851a812f94e8b7c 100644 (file)
@@ -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
index c168ca517002158ddbe67020fdaef5a59af41094..0598e87285dc7e7fff6ba279b04f36634b90103f 100644 (file)
@@ -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);
index 23acee0f9feb3185db9ccfbddace6d0a30829166..7628d0dfdbb37b9fa25d99bc6385627d4bd8cc56 100644 (file)
@@ -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;
 }
 
index 8ec7474a0a3673be826d90cb1a3efedee0d5a4a0..e428b5d76f860e932e2d44906862925ddfd8bd03 100644 (file)
@@ -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.
index c95cacd606636dc868a4af52865eee2b57bf0a63..2cc0369a631f633b3bc3e3148b2ccc05be5dd3a6 100644 (file)
@@ -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;
 }
 
index fb6e8224266e7e6a81b9019b897b219b079e727e..4dbcfd2675f5041bda2285e6950f266cc2fee87a 100644 (file)
@@ -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();
index bd819ab20091a5cf8144bfe4bdb99c9ff8601e7f..23fd1eed9a43bb43a5a0fe256ec190c309ead0dd 100644 (file)
@@ -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;
 }
 
index 96b71d81ea32480fcd5c727a051264d1f22bc5ea..0e10aaafca0a7ba72698c0c5459dda2893a3e8de 100644 (file)
@@ -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;
index 22c129b350285ff7164f86ed36cd9fc4ef5c7116..f6c8433141131732be85ac94fa9ab5dc642c366c 100644 (file)
@@ -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();
                }
        }
 
index 981420d3b5e93da1ed8c549a40f3f216d4f233f5..514866ac497ce845b498c6d33014e92f69443757 100644 (file)
@@ -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_);
index 4939874ab3b8512f9d6282a5595e17fe0b0628af..4d18ce0778e7d5c86fce8bee59631f3aa64908aa 100644 (file)
@@ -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
index 263c91eab905229e1d7bd6770925186726beb1d7..e833a3570f32969ab6f0a236c70e8ea093015e56 100644 (file)
@@ -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());
                }
 
index 50c6e4be87d1013cb5c1f701ed8af1a06a420033..2e97fc07055bd504c859f044529582c2a28a603d 100644 (file)
@@ -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
 
 
index a875d379956aad2cb5081f3d37cd511838fb7669..a6167b5dd901d46c19b4611014112736313ac96c 100644 (file)
  */
 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 &);
index 949061017cd536e2364ec6fd0cdc1702def515fb..236b24ba85f5beb35e565ccfe34ff4934e7e337a 100644 (file)
@@ -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;
        }
 
index 08d726e0c6347de476fa0950798ffa5527574b69..84f13d6ae36a879973c449a15c83dbbf6a09a741 100644 (file)
@@ -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
index 1b37ef262902bc03033db74dfcc4ce387d624292..f0d1b54748089290e20de80d149f0bc774769da6 100644 (file)
@@ -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();
index 66d4b22701e2750567ac5789205de8b34bcb079e..b9c7e7f01a66ee642c2b2cb8a8886411f096ba00 100644 (file)
@@ -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