#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 <QDir>
+#include <QTemporaryFile>
#include "support/lassert.h"
#include "support/regex.h"
#include <fcntl.h>
+#ifdef HAVE_MAGIC_H
+#include <magic.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include <cerrno>
#include <cstdlib>
}
+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)
// 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, "\\", "\\\\"), "\"", "\\\"")
+ "\"";
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();
// 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);
}
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;
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)
// 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 "<path to>/some_script".
string::size_type const size_replace = size_script + 4;
command.replace(pos1, size_replace, quoteName(script, 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
// $[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;
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
}
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;
if (nRead < 0) {
return false;
}
- if (nRead < buf.size() - 1) {
+ if (static_cast<size_t>(nRead) < buf.size() - 1) {
break;
}
buf.resize(buf.size() * 2);
}
-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
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