#include <config.h>
#include "support/convert.h"
-#include "support/systemcall.h"
+#include "support/environment.h"
#include "support/filetools.h"
-#include "support/lstrings.h"
-#include "support/FileInfo.h"
#include "support/forkedcontr.h"
-#include "support/package.h"
-#include "support/path.h"
+#include "support/fs_extras.h"
+#include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/os.h"
+#include "support/package.h"
+#include "support/path.h"
+#include "support/systemcall.h"
// FIXME Interface violation
#include "gettext.h"
#include "debug.h"
#include <boost/assert.hpp>
+#include <boost/filesystem/operations.hpp>
#include <boost/regex.hpp>
-#include <boost/tokenizer.hpp>
#include <fcntl.h>
#include <fstream>
#include <sstream>
-
-// Which part of this is still necessary? (JMarc).
-#if HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
-
#ifndef CXX_GLOBAL_CSTD
using std::fgetc;
using std::isalnum;
using std::ostringstream;
using std::vector;
+namespace fs = boost::filesystem;
namespace lyx {
namespace support {
}
-// Substitutes spaces with underscores in filename (and path)
string const QuoteName(string const & name)
{
return (os::shell() == os::UNIX) ?
// Is a file readable ?
bool IsFileReadable(string const & path)
{
- FileInfo file(path);
- return file.isOK() && file.isRegular() && file.readable();
-}
-
-
-// Is a file read_only?
-// return 1 read-write
-// 0 read_only
-// -1 error (doesn't exist, no access, anything else)
-int IsFileWriteable(string const & path)
-{
- FileInfo fi(path);
-
- if (fi.access(FileInfo::wperm|FileInfo::rperm)) // read-write
- return 1;
- if (fi.readable()) // read-only
- return 0;
- return -1; // everything else.
+ return fs::exists(path) && !fs::is_directory(path) && fs::is_readable(path);
}
/// Returns a vector of all files in directory dir having extension ext.
vector<string> const DirList(string const & dir, string const & ext)
{
- // This is a non-error checking C/system implementation
- string extension;
- if (!ext.empty() && ext[0] != '.')
- extension += '.';
- extension += ext;
-
+ // EXCEPTIONS FIXME. Rewrite needed when we turn on exceptions. (Lgb)
vector<string> dirlist;
- DIR * dirp = ::opendir(dir.c_str());
- if (!dirp) {
+
+ if (!(fs::exists(dir) && fs::is_directory(dir))) {
lyxerr[Debug::FILES]
<< "Directory \"" << dir
<< "\" does not exist to DirList." << endl;
return dirlist;
}
- dirent * dire;
- while ((dire = ::readdir(dirp))) {
- string const fil = dire->d_name;
+ string extension;
+ if (!ext.empty() && ext[0] != '.')
+ extension += '.';
+ extension += ext;
+
+ fs::directory_iterator dit(dir);
+ fs::directory_iterator end;
+ for (; dit != end; ++dit) {
+ string const & fil = dit->leaf();
if (suffixIs(fil, extension)) {
dirlist.push_back(fil);
}
}
- ::closedir(dirp);
return dirlist;
- /* I would have prefered to take a vector<string>& as parameter so
- that we could avoid the copy of the vector when returning.
- Then we would use:
- dirlist.swap(argvec);
- to avoid the copy. (Lgb)
- */
- /* A C++ implementaion will look like this:
- string extension(ext);
- if (extension[0] != '.') extension.insert(0, 1, '.');
- vector<string> dirlist;
- directory_iterator dit("dir");
- while (dit != directory_iterator()) {
- string fil = dit->filename;
- if (prefixIs(fil, extension)) {
- dirlist.push_back(fil);
- }
- ++dit;
- }
- dirlist.swap(argvec);
- return;
- */
}
/* [Otherwise] We have to proceed with the POSIX methods of
looking to `LC_ALL', `LC_xxx', and `LANG'. */
- string lang = GetEnv("LC_ALL");
+ string lang = getEnv("LC_ALL");
if (lang.empty()) {
- lang = GetEnv("LC_MESSAGES");
+ lang = getEnv("LC_MESSAGES");
if (lang.empty()) {
- lang = GetEnv("LANG");
+ lang = getEnv("LANG");
if (lang.empty())
lang = "C";
}
}
- string const language = GetEnv("LANGUAGE");
+ string const language = getEnv("LANGUAGE");
if (lang != "C" && lang != "POSIX" && !language.empty())
lang = language;
string::size_type const pos1 = command.find(token_scriptpath);
if (pos1 == string::npos)
return command;
- // Find the end of the "$$s/some_script" word within command.
- // Assumes that the script name does not contain spaces.
+ // Find the end of the "$$s/some_subdir/some_script" word within
+ // command. Assumes that the script name does not contain spaces.
string::size_type const start_script = pos1 + 4;
string::size_type const pos2 = command.find(' ', start_script);
string::size_type const size_script = pos2 == string::npos?
}
-string const GetEnv(string const & envname)
-{
- // f.ex. what about error checking?
- char const * const ch = getenv(envname.c_str());
- string const envstr = !ch ? "" : ch;
- return envstr;
-}
-
-
-vector<string> const getEnvPath(string const & name)
-{
- typedef boost::char_separator<char> Separator;
- typedef boost::tokenizer<Separator> Tokenizer;
-
- string const env_var = GetEnv(name);
- Separator const separator(string(1, os::path_separator()).c_str());
- Tokenizer const tokens(env_var, separator);
- Tokenizer::const_iterator it = tokens.begin();
- Tokenizer::const_iterator const end = tokens.end();
-
- std::vector<string> vars;
- for (; it != end; ++it)
- vars.push_back(os::internal_path(*it));
-
- return vars;
-}
-
-
-void setEnvPath(string const & name, vector<string> const & env)
-{
- char const separator(os::path_separator());
- std::ostringstream ss;
- vector<string>::const_iterator it = env.begin();
- vector<string>::const_iterator const end = env.end();
- for (; it != end; ++it) {
- if (ss.tellp() > 0)
- ss << separator;
- ss << os::external_path(*it);
- }
- putEnv(name + "=" + ss.str());
-}
-
-
-void prependEnvPath(string const & name, string const & prefix)
-{
- vector<string> env_var = getEnvPath(name);
-
- typedef boost::char_separator<char> Separator;
- typedef boost::tokenizer<Separator> Tokenizer;
-
- Separator const separator(string(1, os::path_separator()).c_str());
-
- // Prepend each new element to the list, removing identical elements
- // that occur later in the list.
- Tokenizer const tokens(prefix, separator);
- vector<string> reversed_tokens(tokens.begin(), tokens.end());
-
- typedef vector<string>::const_reverse_iterator token_iterator;
- token_iterator it = reversed_tokens.rbegin();
- token_iterator const end = reversed_tokens.rend();
- for (; it != end; ++it) {
- vector<string>::iterator remove_it =
- std::remove(env_var.begin(), env_var.end(), *it);
- env_var.erase(remove_it, env_var.end());
- env_var.insert(env_var.begin(), *it);
- }
-
- setEnvPath(name, env_var);
-}
-
-
-bool putEnv(string const & envstr)
-{
- // CHECK Look at and fix this.
- // f.ex. what about error checking?
-
-#if defined (HAVE_SETENV)
- string name;
- string const value = split(envstr, name, '=');
- int const retval = ::setenv(name.c_str(), value.c_str(), true);
-#elif defined (HAVE_PUTENV)
- // this leaks, but what can we do about it?
- // Is doing a getenv() and a free() of the older value
- // a good idea? (JMarc)
- // Actually we don't have to leak...calling putenv like this
- // should be enough: ... and this is obviously not enough if putenv
- // does not make a copy of the string. It is also not very wise to
- // put a string on the free store. If we have to leak we should do it
- // like this:
- char * leaker = new char[envstr.length() + 1];
- envstr.copy(leaker, envstr.length());
- leaker[envstr.length()] = '\0';
- int const retval = ::putenv(leaker);
-
- // If putenv does not make a copy of the char const * this
- // is very dangerous. OTOH if it does take a copy this is the
- // best solution.
- // The only implementation of putenv that I have seen does not
- // allocate memory. _And_ after testing the putenv in glibc it
- // seems that we need to make a copy of the string contents.
- // I will enable the above.
- //int retval = lyx::putenv(envstr.c_str());
-#else
- // No environment setting function. Can this happen?
- int const retval = 1; //return an error condition.
-#endif
- return retval == 0;
-}
-
-
namespace {
-int DeleteAllFilesInDir(string const & path)
-{
- // I have decided that we will be using parts from the boost
- // library. Check out http://www.boost.org/
- // For directory access we will then use the directory_iterator.
- // Then the code will be something like:
- // directory_iterator dit(path);
- // directory_iterator dend;
- // if (dit == dend) {
- // return -1;
- // }
- // for (; dit != dend; ++dit) {
- // string filename(*dit);
- // if (filename == "." || filename == "..")
- // continue;
- // string unlinkpath(AddName(path, filename));
- // lyx::unlink(unlinkpath);
- // }
- // return 0;
- DIR * dir = ::opendir(path.c_str());
- if (!dir)
- return -1;
-
- struct dirent * de;
- int return_value = 0;
- while ((de = readdir(dir))) {
- string const temp = de->d_name;
- if (temp == "." || temp == "..")
- continue;
- string const unlinkpath = AddName (path, temp);
-
- lyxerr[Debug::FILES] << "Deleting file: " << unlinkpath
- << endl;
-
- bool deleted = true;
- FileInfo fi(unlinkpath);
- if (fi.isOK() && fi.isDir()) {
- deleted = (DeleteAllFilesInDir(unlinkpath) == 0);
- deleted &= (rmdir(unlinkpath) == 0);
- } else
- deleted &= (unlink(unlinkpath) == 0);
- if (!deleted)
- return_value = -1;
- }
- closedir(dir);
- return return_value;
-}
-
-
string const createTmpDir(string const & tempdir, string const & mask)
{
lyxerr[Debug::FILES]
} // namespace anon
-int destroyDir(string const & tmpdir)
+bool destroyDir(string const & tmpdir)
{
+
#ifdef __EMX__
Path p(user_lyxdir());
#endif
- if (DeleteAllFilesInDir(tmpdir))
- return -1;
-
- if (rmdir(tmpdir))
- return -1;
-
- return 0;
+ return fs::remove_all(tmpdir) > 0;
}
string const GetFileContents(string const & fname)
{
- FileInfo finfo(fname);
- if (finfo.exist()) {
+ if (fs::exists(fname)) {
ifstream ifs(fname.c_str());
ostringstream ofs;
if (ifs && ofs) {
if (!what[0].matched)
break;
}
- result = what.str(1) + GetEnv(what.str(2)) + what.str(3);
+ result = what.str(1) + getEnv(what.str(2)) + what.str(3);
}
return result;
}
// If the file can be found directly, we just return a
// absolute path version of it.
- if (FileInfo(fil).exist())
+ if (fs::exists(fil))
return MakeAbsPath(fil);
// No we try to find it using kpsewhich.
a += '#';
a += OnlyFilename(filename);
a += '#';
- FileInfo const fileinfo(a);
- if (fileinfo.exist())
+ if (fs::exists(a))
unlink(a);
}
// If the original is newer than the copy, then copy the original
// to the new directory.
- FileInfo f1(file1);
- FileInfo f2(file2);
int cmp = 0;
- if (f1.exist() && f2.exist()) {
- double const tmp = difftime(f1.getModificationTime(),
- f2.getModificationTime());
+ if (fs::exists(file1) && fs::exists(file2)) {
+ double const tmp = difftime(fs::last_write_time(file1),
+ fs::last_write_time(file2));
if (tmp != 0)
cmp = tmp > 0 ? 1 : -1;
- } else if (f1.exist()) {
+ } else if (fs::exists(file1)) {
cmp = 1;
- } else if (f2.exist()) {
+ } else if (fs::exists(file2)) {
cmp = -1;
}