X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Ffiletools.cpp;h=60bd72f9054b5e6d9e3498ee2f8efcaa28159943;hb=76e99e9a20cf635d20effa597551f3a9af484465;hp=1f794f2c9ca9e9b82e364b02f8d396dff9a35b3c;hpb=1af2242c7e9c3dd4edd1ddba5f65e5de5c5e600a;p=lyx.git diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 1f794f2c9c..60bd72f905 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -21,10 +21,12 @@ #include +#include "LyX.h" #include "LyXRC.h" #include "support/filetools.h" +#include "support/convert.h" #include "support/debug.h" #include "support/environment.h" #include "support/gettext.h" @@ -35,10 +37,9 @@ #include "support/PathChanger.h" #include "support/Systemcall.h" #include "support/qstring_helpers.h" +#include "support/TempFile.h" #include -#include -#include #include "support/lassert.h" #include "support/regex.h" @@ -52,6 +53,7 @@ #endif #include +#include #include #include @@ -416,24 +418,6 @@ FileName const imageLibFileSearch(string & dir, string const & name, } -int iconScaleFactor(FileName const & image) -{ - int imgsize = QImage(toqstr(image.absFileName())).height(); - if (imgsize <= 0) - return 100; - - // default icon size - int iconsize = 20; - - string dir = "images"; - FileName const fn = imageLibFileSearch(dir, "iconsize.png"); - if (!fn.empty()) - iconsize = QImage(toqstr(fn.absFileName())).height(); - - return (100 * iconsize + imgsize / 2)/imgsize; -} - - string const commandPrep(string const & command_in) { static string const token_scriptpath = "$$s/"; @@ -475,25 +459,53 @@ string const commandPrep(string const & command_in) } -static string createTempFile(QString const & mask) +FileName const tempFileName(string const & mask, bool const dir) { - // FIXME: This is not safe. QTemporaryFile creates a file in open(), - // but the file is deleted when qt_tmp goes out of scope. - // Therefore the next call to createTempFile() may create the - // same file again. To make this safe the QTemporaryFile object - // needs to be kept for the whole life time of the temp file name. - // This could be achieved by creating a class TempDir (like - // TempFile, but using a currentlky non-existing - // QTemporaryDirectory object). - QTemporaryFile qt_tmp(mask + ".XXXXXXXXXXXX"); - if (qt_tmp.open()) { - string const temp_file = fromqstr(qt_tmp.fileName()); - LYXERR(Debug::FILES, "Temporary file `" << temp_file << "' created."); - return temp_file; + FileName tempfile = TempFile(mask).name(); + // Since the QTemporaryFile object is destroyed at function return + // (which is what is intended here), the next call to this function + // may return the same file name again. + // Thus, in order to prevent race conditions, we track returned names + // and create our own unique names if QTemporaryFile returns a name again. + if (tmp_names_.find(tempfile.absFileName()) == tmp_names_.end()) { + tmp_names_.insert(tempfile.absFileName()); + return tempfile; } - LYXERR(Debug::FILES, "Unable to create temporary file with following template: " - << qt_tmp.fileTemplate()); - return string(); + + // OK, we need another name. Simply append digits. + FileName tmp = tempfile; + string ext; + if (!dir) { + // Store and remove extensions + ext = "." + tempfile.extension(); + tmp.changeExtension(""); + } + for (int i = 1; i < INT_MAX ;++i) { + // Append digit to filename and re-add extension + string const new_fn = + tmp.absFileName() + convert(i) + ext; + if (tmp_names_.find(new_fn) == tmp_names_.end()) { + tmp_names_.insert(new_fn); + tempfile.set(new_fn); + return tempfile; + } + } + + // This should not happen! + LYXERR0("tempFileName(): Could not create unique temp file name!"); + return tempfile; +} + + +void removeTempFile(FileName const & fn) +{ + if (!fn.exists()) + return; + + string const abs = fn.absFileName(); + if (tmp_names_.find(abs) != tmp_names_.end()) + tmp_names_.erase(abs); + fn.removeFile(); } @@ -503,7 +515,8 @@ static FileName createTmpDir(FileName const & tempdir, string const & mask) << "createTmpDir: mask=`" << mask << '\''); QFileInfo tmp_fi(QDir(toqstr(tempdir.absFileName())), toqstr(mask)); - FileName const tmpfl(createTempFile(tmp_fi.absoluteFilePath())); + FileName const tmpfl = + tempFileName(fromqstr(tmp_fi.absoluteFilePath()) + ".XXXXXXXXXXXX", true); if (tmpfl.empty() || !tmpfl.createDirectory(0700)) { LYXERR0("LyX could not create temporary directory in " << tempdir @@ -662,35 +675,6 @@ string const onlyFileName(string const & fname) } -// Create absolute path. If impossible, don't do anything -// Supports ./ and ~/. Later we can add support for ~logname/. (Asger) -string const expandPath(string const & path) -{ - // checks for already absolute path - string rTemp = replaceEnvironmentPath(path); - if (FileName::isAbsolute(rTemp)) - return rTemp; - - string temp; - string const copy = rTemp; - - // Split by next / - rTemp = split(rTemp, temp, '/'); - - if (temp == ".") - return FileName::getcwd().absFileName() + '/' + rTemp; - - if (temp == "~") - return Package::get_home_dir().absFileName() + '/' + rTemp; - - if (temp == "..") - return makeAbsPath(copy).absFileName(); - - // Don't know how to handle this - return copy; -} - - // Search the string for ${VAR} and $VAR and replace VAR using getenv. string const replaceEnvironmentPath(string const & path) { @@ -702,42 +686,84 @@ string const replaceEnvironmentPath(string const & path) // $[A-Za-z_][A-Za-z_0-9]* static string const envvar = "[$]([A-Za-z_][A-Za-z_0-9]*)"; - static regex const envvar_br_re("(.*)" + envvar_br + "(.*)"); - static regex const envvar_re("(.*)" + envvar + "(.*)"); - string result = path; - while (1) { - smatch what; - if (!regex_match(result, what, envvar_br_re)) { - if (!regex_match(result, what, envvar_re)) - break; + // Coverity thinks that the regex constructor can return an + // exception. We know that it is not true since our regex are + // hardcoded, but we have to protect against that nevertheless. + try { + static regex const envvar_br_re("(.*)" + envvar_br + "(.*)"); + static regex const envvar_re("(.*)" + envvar + "(.*)"); + string result = path; + while (1) { + smatch what; + if (!regex_match(result, what, envvar_br_re)) { + if (!regex_match(result, what, envvar_re)) + break; + } + string env_var = getEnv(what.str(2)); + result = what.str(1) + env_var + what.str(3); } - string env_var = getEnv(what.str(2)); - result = what.str(1) + env_var + what.str(3); + return result; + } catch (exception const & e) { + LYXERR0("Something is very wrong: " << e.what()); + return path; } - return result; } // Return a command prefix for setting the environment of the TeX engine. -string latexEnvCmdPrefix(string const & path) +string latexEnvCmdPrefix(string const & path, string const & lpath) { - if (path.empty() || lyxrc.texinputs_prefix.empty()) + bool use_lpath = !(lpath.empty() || lpath == "." || lpath == "./"); + + if (path.empty() || (lyxrc.texinputs_prefix.empty() && !use_lpath)) return string(); - string const texinputs_prefix = os::latex_path_list( + string texinputs_prefix = lyxrc.texinputs_prefix.empty() ? string() + : os::latex_path_list( replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const allother_prefix = os::latex_path_list(path); string const sep = string(1, os::path_separator(os::TEXENGINE)); string const texinputs = getEnv("TEXINPUTS"); + string const bibinputs = getEnv("BIBINPUTS"); + string const bstinputs = getEnv("BSTINPUTS"); + string const texfonts = getEnv("TEXFONTS"); + + if (use_lpath) { + string const abslpath = FileName::isAbsolute(lpath) + ? os::latex_path(lpath) + : os::latex_path(FileName(path + "/" + lpath).realPath()); + if (texinputs_prefix.empty()) + texinputs_prefix = abslpath; + else if (suffixIs(texinputs_prefix, sep)) + texinputs_prefix.append(abslpath + sep); + else + texinputs_prefix.append(sep + abslpath); + } if (os::shell() == os::UNIX) return "env TEXINPUTS=\"." + sep + texinputs_prefix - + sep + texinputs + "\" "; + + sep + texinputs + "\" " + + "BIBINPUTS=\"." + sep + allother_prefix + + sep + bibinputs + "\" " + + "BSTINPUTS=\"." + sep + allother_prefix + + sep + bstinputs + "\" " + + "TEXFONTS=\"." + sep + allother_prefix + + sep + texfonts + "\" "; else - // NOTE: the dummy blank dir is necessary to force the + // NOTE: the dummy blank dirs are necessary to force the // QProcess parser to quote the argument (see bug 9453) return "cmd /d /c set \"TEXINPUTS=." + sep + " " - + sep + texinputs_prefix - + sep + texinputs + "\" & "; + + sep + texinputs_prefix + + sep + texinputs + "\" & " + + "set \"BIBINPUTS=." + sep + " " + + sep + allother_prefix + + sep + bibinputs + "\" & " + + "set \"BSTINPUTS=." + sep + " " + + sep + allother_prefix + + sep + bstinputs + "\" & " + + "set \"TEXFONTS=." + sep + " " + + sep + allother_prefix + + sep + texfonts + "\" & "; } @@ -946,13 +972,11 @@ docstring const makeDisplayPath(string const & path, unsigned int threshold) if (dstr.empty()) { // Yes, filename itself is too long. // Pick the start and the end of the filename. - dstr = from_utf8(onlyFileName(path)); - docstring const head = dstr.substr(0, threshold / 2 - 3); - - docstring::size_type len = dstr.length(); - docstring const tail = - dstr.substr(len - threshold / 2 - 2, len - 1); - dstr = head + from_ascii("...") + tail; + docstring fstr = from_utf8(onlyFileName(path)); + dstr = fstr; + if (support::truncateWithEllipsis(dstr, threshold / 2)) + dstr += fstr.substr(fstr.length() - threshold / 2 - 2, + docstring::npos); } return from_utf8(os::external_path(prefix + to_utf8(dstr))); @@ -1010,8 +1034,12 @@ cmd_ret const runCommand(string const & cmd) // pstream (process stream), with the // variants ipstream, opstream + if (verbose) + lyxerr << "\nRunning: " << cmd << endl; + else + LYXERR(Debug::INFO,"Running: " << cmd); + #if defined (_WIN32) - int fno; STARTUPINFO startup; PROCESS_INFORMATION process; SECURITY_ATTRIBUTES security; @@ -1053,7 +1081,7 @@ cmd_ret const runCommand(string const & cmd) 0, 0, &startup, &process)) { CloseHandle(process.hThread); - fno = _open_osfhandle((long)in, _O_RDONLY); + int fno = _open_osfhandle((intptr_t)in, _O_RDONLY); CloseHandle(out); inf = _fdopen(fno, "r"); } @@ -1081,10 +1109,14 @@ cmd_ret const runCommand(string const & cmd) #if defined (_WIN32) WaitForSingleObject(process.hProcess, INFINITE); + DWORD pret; + if (!GetExitCodeProcess(process.hProcess, &pret)) + pret = -1; if (!infile.empty()) CloseHandle(startup.hStdInput); CloseHandle(process.hProcess); - int const pret = fclose(inf); + if (fclose(inf) != 0) + pret = -1; #elif defined (HAVE_PCLOSE) int const pret = pclose(inf); #elif defined (HAVE__PCLOSE) @@ -1100,7 +1132,8 @@ cmd_ret const runCommand(string const & cmd) } -FileName const findtexfile(string const & fil, string const & /*format*/) +FileName const findtexfile(string const & fil, string const & /*format*/, + bool const onlykpse) { /* There is no problem to extend this function too use other methods to look for files. It could be setup to look @@ -1113,9 +1146,11 @@ FileName const findtexfile(string const & fil, string const & /*format*/) // If the file can be found directly, we just return a // absolute path version of it. - FileName const absfile(makeAbsPath(fil)); - if (absfile.exists()) - return absfile; + if (!onlykpse) { + FileName const absfile(makeAbsPath(fil)); + if (absfile.exists()) + return absfile; + } // Now we try to find it using kpsewhich. // It seems from the kpsewhich manual page that it is safe to use @@ -1223,14 +1258,17 @@ int fileLock(const char * lock_file) int fd = -1; #if defined(HAVE_LOCKF) fd = open(lock_file, O_CREAT|O_APPEND|O_SYNC|O_RDWR, 0666); + if (fd == -1) + return -1; if (lockf(fd, F_LOCK, 0) != 0) { close(fd); - return(-1); + return -1; } #endif - return(fd); + return fd; } + void fileUnlock(int fd, const char * /* lock_file*/) { #if defined(HAVE_LOCKF)