X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Ffiletools.cpp;h=040272aade620e406bed47dcca8947126c0c763d;hb=dae8555234f0e5c8358b91c307d91b219c664617;hp=5891e79fec62c6b89346ed3e611a265e8a7bc1ca;hpb=d7320ad89b26bb89f8f133801c6a452005e5bff3;p=lyx.git diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 5891e79fec..040272aade 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -30,17 +30,25 @@ #include "support/gettext.h" #include "support/lstrings.h" #include "support/os.h" +#include "support/Messages.h" #include "support/Package.h" -#include "support/Path.h" +#include "support/PathChanger.h" #include "support/Systemcall.h" #include "support/qstring_helpers.h" #include +#include #include "support/lassert.h" #include "support/regex.h" #include +#ifdef HAVE_MAGIC_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif #include #include @@ -89,6 +97,60 @@ bool isValidDVIFileName(string const & filename) } +bool isBinaryFile(FileName const & filename) +{ + bool isbinary = false; + if (filename.empty() || !filename.exists()) + return isbinary; + +#ifdef HAVE_MAGIC_H + magic_t magic_cookie = magic_open(MAGIC_MIME_ENCODING); + if (magic_cookie) { + bool detected = true; + if (magic_load(magic_cookie, NULL) != 0) { + LYXERR(Debug::FILES, "isBinaryFile: " + "Could not load magic database - " + << magic_error(magic_cookie)); + detected = false; + } else { + char const *charset = magic_file(magic_cookie, + filename.toFilesystemEncoding().c_str()); + isbinary = contains(charset, "binary"); + } + magic_close(magic_cookie); + if (detected) + return isbinary; + } +#endif + // Try by looking for binary chars at the beginning of the file. + // Note that this is formally not correct, since count_bin_chars + // expects utf8, and the passed string can be anything: plain text + // in any encoding, or really binary data. In practice it works, + // since QString::fromUtf8() drops invalid utf8 sequences, and + // while the exact number may not be correct, we still get a high + // number for truly binary files. + + ifstream ifs(filename.toFilesystemEncoding().c_str()); + if (!ifs) + return isbinary; + + // Maximum strings to read + int const max_count = 50; + + // Maximum number of binary chars allowed + int const max_bin = 5; + + int count = 0; + int binchars = 0; + string str; + while (count++ < max_count && !ifs.eof()) { + getline(ifs, str); + binchars += count_bin_chars(str); + } + return binchars > max_bin; +} + + string const latex_path(string const & original_path, latex_path_extension extension, latex_path_dots dots) @@ -177,6 +239,8 @@ string const quoteName(string const & name, quote_style style) // simple parser in Systemcall.cpp do the substitution. return '"' + subst(name, "\"", "\\\"") + '"'; #endif + case quote_shell_filename: + return quoteName(os::external_path(name), quote_shell); case quote_python: return "\"" + subst(subst(name, "\\", "\\\\"), "\"", "\\\"") + "\""; @@ -241,8 +305,14 @@ FileName const fileSearch(string const & path, string const & name, return mode == may_not_exist ? fullname : FileName(); // Only add the extension if it is not already the extension of // fullname. - if (getExtension(fullname.absFileName()) != ext) + if (getExtension(fullname.absFileName()) != ext) { + if (mode == check_hidpi) { + FileName fullname2x = FileName(addExtension(fullname.absFileName() + "@2x", ext)); + if (fullname2x.isReadableFile()) + return fullname2x; + } fullname = FileName(addExtension(fullname.absFileName(), ext)); + } if (fullname.isReadableFile() || mode == may_not_exist) return fullname; return FileName(); @@ -254,20 +324,21 @@ FileName const fileSearch(string const & path, string const & name, // 2) build_lyxdir (if not empty) // 3) system_lyxdir FileName const libFileSearch(string const & dir, string const & name, - string const & ext) + string const & ext, search_mode mode) { FileName fullname = fileSearch(addPath(package().user_support().absFileName(), dir), - name, ext); + name, ext, mode); if (!fullname.empty()) return fullname; if (!package().build_support().empty()) fullname = fileSearch(addPath(package().build_support().absFileName(), dir), - name, ext); + name, ext, mode); if (!fullname.empty()) return fullname; - return fileSearch(addPath(package().system_support().absFileName(), dir), name, ext); + return fileSearch(addPath(package().system_support().absFileName(), dir), + name, ext, mode); } @@ -282,7 +353,7 @@ FileName const i18nLibFileSearch(string const & dir, string const & name, each po file is able to tell us its name. (JMarc) */ - string lang = to_ascii(_(languageTestString())); + string lang = getGuiMessages().language(); string const language = getEnv("LANGUAGE"); if (!lang.empty() && !language.empty()) lang = language; @@ -322,25 +393,29 @@ FileName const i18nLibFileSearch(string const & dir, string const & name, FileName const imageLibFileSearch(string & dir, string const & name, - string const & ext) + string const & ext, search_mode mode) { if (!lyx::lyxrc.icon_set.empty()) { string const imagedir = addPath(dir, lyx::lyxrc.icon_set); - FileName const fn = libFileSearch(imagedir, name, ext); + FileName const fn = libFileSearch(imagedir, name, ext, mode); if (fn.exists()) { dir = imagedir; return fn; } } - return libFileSearch(dir, name, ext); + return libFileSearch(dir, name, ext, mode); } -string const libScriptSearch(string const & command_in, quote_style style) +string const commandPrep(string const & command_in) { static string const token_scriptpath = "$$s/"; + string const python_call = "python -tt"; string command = command_in; + if (prefixIs(command_in, python_call)) + command = os::python() + command_in.substr(python_call.length()); + // Find the starting position of "$$s/" string::size_type const pos1 = command.find(token_scriptpath); if (pos1 == string::npos) @@ -360,6 +435,10 @@ string const libScriptSearch(string const & command_in, quote_style style) // Replace "$$s/" with "" command.erase(pos1, 4); } else { + quote_style style = quote_shell; + if (prefixIs(command, os::python())) + style = quote_python; + // Replace "$$s/foo/some_script" with "/some_script". string::size_type const size_replace = size_script + 4; command.replace(pos1, size_replace, quoteName(script, style)); @@ -369,12 +448,35 @@ string const libScriptSearch(string const & command_in, quote_style style) } +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 @@ -573,8 +675,8 @@ 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 envvar_br_re("(.*)" + envvar_br + "(.*)"); - static regex envvar_re("(.*)" + envvar + "(.*)"); + static regex const envvar_br_re("(.*)" + envvar_br + "(.*)"); + static regex const envvar_re("(.*)" + envvar + "(.*)"); string result = path; while (1) { smatch what; @@ -604,8 +706,15 @@ string latexEnvCmdPrefix(string const & path) return "env TEXINPUTS=\"." + sep + texinputs_prefix + sep + texinputs + "\" "; else - return "cmd /d /c set TEXINPUTS=." + sep + texinputs_prefix - + sep + texinputs + "&"; +#ifndef USE_QPROCESS + return "cmd /d /c set \"TEXINPUTS=." + + sep + texinputs_prefix + + sep + texinputs + "\"&"; +#else + return "cmd /d /c set \"\"\"TEXINPUTS=." + + sep + texinputs_prefix + + sep + texinputs + "\"\"\"&"; +#endif } @@ -831,7 +940,7 @@ bool readLink(FileName const & file, FileName & link) string const encoded = file.toFilesystemEncoding(); #ifdef HAVE_DEF_PATH_MAX char linkbuffer[PATH_MAX + 1]; - int const nRead = ::readlink(encoded.c_str(), + ssize_t const nRead = ::readlink(encoded.c_str(), linkbuffer, sizeof(linkbuffer) - 1); if (nRead <= 0) return false; @@ -845,7 +954,7 @@ bool readLink(FileName const & file, FileName & link) if (nRead < 0) { return false; } - if (nRead < buf.size() - 1) { + if (static_cast(nRead) < buf.size() - 1) { break; } buf.resize(buf.size() * 2); @@ -1016,59 +1125,6 @@ FileName const findtexfile(string const & fil, string const & /*format*/) } -void readBB_lyxerrMessage(FileName const & file, bool & zipped, - string const & message) -{ - LYXERR(Debug::GRAPHICS, "[readBB_from_PSFile] " << message); - // FIXME: Why is this func deleting a file? (Lgb) - if (zipped) - file.removeFile(); -} - - -string const readBB_from_PSFile(FileName const & file) -{ - // in a (e)ps-file it's an entry like %%BoundingBox:23 45 321 345 - // It seems that every command in the header has an own line, - // getline() should work for all files. - // On the other hand some plot programs write the bb at the - // end of the file. Than we have in the header: - // %%BoundingBox: (atend) - // In this case we must check the end. - bool zipped = file.isZippedFile(); - FileName const file_ = zipped ? unzipFile(file) : file; - string const format = file_.guessFormatFromContents(); - - if (format != "eps" && format != "ps") { - readBB_lyxerrMessage(file_, zipped,"no(e)ps-format"); - return string(); - } - - static lyx::regex bbox_re( - "^%%BoundingBox:\\s*([[:digit:]]+)\\s+([[:digit:]]+)\\s+([[:digit:]]+)\\s+([[:digit:]]+)"); - ifstream is(file_.toFilesystemEncoding().c_str()); - while (is) { - string s; - getline(is,s); - lyx::smatch what; - if (regex_match(s, what, bbox_re)) { - // Our callers expect the tokens in the string - // separated by single spaces. - // FIXME: change return type from string to something - // sensible - ostringstream os; - os << what.str(1) << ' ' << what.str(2) << ' ' - << what.str(3) << ' ' << what.str(4); - string const bb = os.str(); - readBB_lyxerrMessage(file_, zipped, bb); - return bb; - } - } - readBB_lyxerrMessage(file_, zipped, "no bb found"); - return string(); -} - - int compare_timestamps(FileName const & file1, FileName const & file2) { // If the original is newer than the copy, then copy the original @@ -1116,6 +1172,29 @@ bool prefs2prefs(FileName const & filename, FileName const & tempfile, bool lfun return true; } +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 (lockf(fd, F_LOCK, 0) != 0) { + close(fd); + return(-1); + } +#endif + return(fd); +} + +void fileUnlock(int fd, const char * /* lock_file*/) +{ +#if defined(HAVE_LOCKF) + if (fd >= 0) { + if (lockf(fd, F_ULOCK, 0)) + LYXERR0("Can't unlock the file."); + close(fd); + } +#endif +} } //namespace support } // namespace lyx