OpenASIP  2.0
FileSystem.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file FileSystem.cc
26  *
27  * Implementation of FileSystem class.
28  *
29  * @author Pekka J??skel?inen (pekka.jaaskelainen-no.spam-tut.fi)
30  * @author Viljami Korhonen 2007 (viljami.korhonen-no.spam-tut.fi)
31  * @author Esa M??tt? 2007 (esa.maatta-no.spam-tut.fi)
32  * @note rating: red
33  */
34 
35 #include <fstream>
36 #include <string>
37 #include <vector>
38 #include <glob.h>
39 #include <cerrno>
40 #include <cstdio>
41 #include <unistd.h> // for truncate
42 #include <sys/types.h> // for truncate
43 
44 /* This must be before any of the boost inclusions, to ensure
45  * that the boost filesystem API we get agrees with what is
46  * exposed through the header. */
47 #include "FileSystem.hh"
48 
49 #include <boost/filesystem/operations.hpp>
50 #include <boost/filesystem/convenience.hpp>
51 #include <boost/filesystem/exception.hpp>
52 #include "CompilerWarnings.hh"
53 IGNORE_CLANG_WARNING("-Wkeyword-macro")
54 #include <boost/regex.hpp>
56 #include <boost/format.hpp>
57 
58 #include "MathTools.hh"
59 #include "tce_config.h"
60 
61 using std::string;
62 using std::vector;
63 
64 const std::string FileSystem::DIRECTORY_SEPARATOR =
65 string(DIR_SEPARATOR);
66 const std::string FileSystem::CURRENT_DIRECTORY = ".";
67 const std::string FileSystem::STRING_WILD_CARD = "*";
68 
69 using namespace boost::filesystem;
70 
71 /**
72  * Returns the path part of the given file name.
73  *
74  * @param fileName A file name with a (partial or absolute) path.
75  * @return Path part of the file name.
76  *
77  */
78 std::string
79 FileSystem::directoryOfPath(const std::string fileName) {
80 
81  Path origString(fileName);
82  string file = origString.string();
83  Path DS(DIRECTORY_SEPARATOR);
84  string::size_type lastPathPos = file.rfind(DS.string());
85  if (lastPathPos == string::npos) {
86  return CURRENT_DIRECTORY;
87  }
88 
89  string dirPath = file.substr(0, lastPathPos);
90  Path path(dirPath);
91  return path.string();
92 }
93 
94 /**
95  * Returns the file part of the given path name.
96  *
97  * @param pathName The path name.
98  * @return The file part of the path name.
99  */
100 std::string
101 FileSystem::fileOfPath(const std::string pathName) {
102  if (!isPath(pathName)) {
103  return pathName;
104  }
105  Path origString(pathName);
106  string path = origString.string();
107  Path DS(DIRECTORY_SEPARATOR);
108  unsigned int index = path.find_last_of(DIRECTORY_SEPARATOR);
109  return path.substr(index + 1);
110 }
111 
112 /**
113  * Tests if a file or directory can be created by user.
114  *
115  * The file or directory can be created if:
116  * - it does not already exist,
117  * - the path where it should be created exists and is writable.
118  *
119  * @param fileName Name of the file or directory to test.
120  * @return True if file or directory can be created, false otherwise.
121  */
122 bool
123 FileSystem::fileIsCreatable(const std::string fileName) {
124 
125  if (fileName == "") {
126  return false;
127  }
128 
129  std::string destPath = directoryOfPath(fileName);
130 
131  return !fileExists(fileName) && fileExists(destPath) &&
132  fileIsWritable(destPath);
133 }
134 
135 /**
136  * Returns the current working directory.
137  *
138  * @return The current working directory or, in case of error, an empty
139  * string.
140  */
141 std::string
143 
144  // the amount of bytes to stretch the char buffer if the path doesn't
145  // fit in it
146  const int increment = 100;
147  int bufSize = 200;
148  char* buf = new char[bufSize];
149 
150  // sets errno to ERANGE if buffer was too small
151  char* retValue = getcwd(buf, bufSize);
152 
153  // grow the buffer until the path fits in it
154  while (retValue == NULL && errno == ERANGE) {
155  delete[] buf;
156  bufSize += increment;
157  buf = new char[bufSize];
158  retValue = getcwd(buf, bufSize);
159  }
160 
161  std::string dirName = "";
162  if (retValue == NULL) {
163 
164  std::string procName = "FileSystem::currentWorkingDir";
165  std::string errorMsg = "Current working directory cannot be read.";
166  Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
167 
168  assert(errno == EACCES);
169  } else {
170  dirName = buf;
171  }
172 
173  delete[] buf;
174  Path path(dirName);
175  return path.string();
176 }
177 
178 /**
179  * Changes the working directory to a new one
180  *
181  * @param path The new working directory to be set
182  * @return true on success, false on error
183  */
184 bool
185 FileSystem::changeWorkingDir(const std::string& path) {
186  return (chdir(path.c_str()) == 0);
187 }
188 
189 /**
190  * Searches path names that matches the pattern and stores the results
191  * in string vector.
192  *
193  * @param pattern The pattern to be matched.
194  * @param filenames Results are stored here.
195  */
196 void
198  const std::string& pattern,
199  std::vector<std::string>& filenames) {
200 
201  glob_t globbuf;
202  glob(pattern.c_str(), 0, NULL, &globbuf);
203  for (size_t i = 0; i < globbuf.gl_pathc; i++) {
204  filenames.push_back(globbuf.gl_pathv[i]);
205  }
206  // reserved memory is freed
207  globfree(&globbuf);
208 }
209 
210 /**
211  * Replaces "~/" with "$HOME/". Doesn't replace ~user.
212  *
213  * @param stringWithTilde A string containing tilde to expanded.
214  * @return The string with tilde expanded.
215  */
216 string
217 FileSystem::expandTilde(const std::string& stringWithTilde) {
218  string withoutTilde = stringWithTilde;
219  if (withoutTilde == "~" || withoutTilde.substr(0, 2) == "~/") {
220  withoutTilde.erase(0, 1);
221  withoutTilde.insert(0, FileSystem::homeDirectory());
222 
223  }
224  return withoutTilde;
225 }
226 
227 /**
228  * Checks if the pathName is a string representing an absolute path.
229  *
230  * @param pathName The investigated path.
231  * @return True, if it is an absolute path, false otherwise.
232  */
233 bool
234 FileSystem::isAbsolutePath(const std::string& pathName) {
235  Path path(pathName);
236  string pathString = path.string();
237  Path DS(DIRECTORY_SEPARATOR);
238  return pathString.substr(0, 1) ==
239  DS.string() ? true : false;
240 }
241 
242 /**
243  * Checks if the pathName is a string representing a relative path.
244  *
245  * Path is relative path, if it is not absolute path and not empty
246  * string.
247  *
248  * @param pathName The investigated path.
249  * @return True, if it is a relative path, false otherwise.
250  */
251 bool
252 FileSystem::isRelativePath(const std::string& pathName) {
253  Path path(pathName);
254  string pathString = path.string();
255  return !isAbsolutePath(pathString) && !pathString.empty();
256 }
257 
258 /**
259  * Checks if the pathName is a string representing path (relative or absolute).
260  *
261  * @param pathName The investigated path.
262  * @return True, if it is a relative path, false otherwise.
263  */
264 bool
265 FileSystem::isPath(const std::string& pathName) {
266  return (!pathName.empty() &&
267  (isRelativePath(pathName) || isAbsolutePath(pathName)));
268 }
269 
270 /**
271  * Returns the file extension of an file, if anything is found.
272  *
273  * If not extension is found, an empty string is returned.
274  *
275  * @param fileName The name of the file.
276  * @return The file extension.
277  */
278 string
279 FileSystem::fileExtension(const std::string& fileName) {
280  const Path path(fileName);
281  return boost::filesystem::extension(path);
282 }
283 
284 /**
285  * Returns the name of the file without file extension.
286  *
287  * @param fileName The name of the file.
288  * @return The name of the file without the file extension.
289  */
290 string
291 FileSystem::fileNameBody(const std::string& fileName) {
292  const Path path(fileName);
293  return boost::filesystem::basename(path);
294 }
295 
296 /**
297  * Returns the given path as absolute path.
298  *
299  * @param pathName The path.
300  * @return The absolute path.
301  */
302 string
303 FileSystem::absolutePathOf(const std::string& pathName) {
304  string absolutePath("");
305  if (isAbsolutePath(pathName)) {
306  absolutePath = pathName;
307  } else {
308  absolutePath = currentWorkingDir() + DIRECTORY_SEPARATOR + pathName;
309  }
310  Path path(absolutePath);
311  path.normalize();
312  return path.string();
313 }
314 
315 /**
316  * Grants execute rights for user to a file.
317  *
318  * @param fileName File whitch execute rights are to be changed.
319  * @return True if operation was succesfull, otherwise false.
320  */
321 bool
322 FileSystem::setFileExecutable(const std::string fileName) {
323  if (fileIsWritable(fileName) && fileIsReadable(fileName)) {
324  if (chmod(fileName.c_str(), S_IXUSR | S_IRUSR | S_IWUSR) != 0) {
325  return false;
326  }
327  } else if (fileIsWritable(fileName)) {
328  if (chmod(fileName.c_str(), S_IXUSR | S_IWUSR) != 0) {
329  return false;
330  }
331  } else if (fileIsReadable(fileName)) {
332  if (chmod(fileName.c_str(), S_IXUSR | S_IRUSR) != 0) {
333  return false;
334  }
335  } else {
336  if (chmod(fileName.c_str(), S_IXUSR) != 0) {
337  return false;
338  }
339  }
340  return true;
341 }
342 
343 /**
344  * Returns last modification time of a file.
345  *
346  * If last modification time can't be resolved, std::time_t(-1) is returned.
347  *
348  * @param filePath Path to the file.
349  * @return Time of the last modification to the file.
350  */
351 std::time_t
352 FileSystem::lastModificationTime(const std::string& filePath) {
353  if (!isAbsolutePath(filePath) || !fileExists(filePath)) {
354  return std::time_t(-1);
355  }
356 
357  std::time_t lastModTime;
358  try {
359  lastModTime = boost::filesystem::last_write_time(filePath);
360  } catch (...) {
361  lastModTime = std::time_t(-1);
362  }
363 
364  return lastModTime;
365 }
366 
367 /**
368  * Returns current size of the file in bytes.
369  *
370  * If file size can't be resolved, static_cast<uintmax_t>(-1) is returned.
371  *
372  * @param filePath Path to the file.
373  * @return Size of the file in bytes.
374  */
375 uintmax_t
376 FileSystem::sizeInBytes(const std::string& filePath) {
377  if (!isAbsolutePath(filePath) || !fileExists(filePath)) {
378  return static_cast<uintmax_t>(-1);
379  }
380 
381  uintmax_t fileSize;
382  try {
383  fileSize = boost::filesystem::file_size(filePath);
384  } catch (...) {
385  fileSize = static_cast<uintmax_t>(-1);
386  }
387 
388  return fileSize;
389 }
390 
391 /**
392  * Creates a directory if it doesn't already exist.
393  *
394  * All non-existing directories in the path are created.
395  *
396  * @param path The path of directory.
397  * @return True if directory is created, false otherwise.
398  */
399 bool
400 FileSystem::createDirectory(const std::string& path) {
401  std::string p = path;
402  if (!isAbsolutePath(p)) {
403  p = absolutePathOf(p);
404  }
405  Path DS(DIRECTORY_SEPARATOR);
406  Path orPath(p.substr(1));
407  string origPath = orPath.string();
408  string currentPath = DS.string();
409  while (origPath.size() > 0) {
410  string::size_type pos = origPath.find(DS.string());
411  if (pos == string::npos) {
412  currentPath += origPath;
413  origPath = "";
414  } else {
415  currentPath += origPath.substr(0, pos);
416  origPath.replace(0, pos + 1, "");
417  }
418  try {
419  Path dirPath(currentPath);
420  if (!boost::filesystem::exists(dirPath)) {
421  boost::filesystem::create_directory(dirPath);
422  }
423  } catch (...) {
424  // directory creation failed, probably because of lacking rights
425  return false;
426  }
427  currentPath += DS.string();
428  }
429  return true;
430 }
431 
432 /**
433  * Creates a temporary directory to the given path
434  *
435  * @param path Path to create the temporary directory in
436  * @param tempDirPrefix Prefix string before randomly generated string part.
437  * @return Full path to the generated temporary directory.
438  * Empty string on error.
439  */
440 std::string
442  const std::string& path,
443  const std::string& tempDirPrefix) {
444  const int RANDOM_CHARS = 10;
445  const string DS(DIRECTORY_SEPARATOR);
446  string tempDir = path + DS + tempDirPrefix;
447 
448  for (int i = 0; i < RANDOM_CHARS || fileExists(tempDir); ++i) {
449  tempDir += static_cast<char>(MathTools::random('0', '9'));
450  tempDir += static_cast<char>(MathTools::random('a', 'z'));
451  tempDir += static_cast<char>(MathTools::random('A', 'Z'));
452  }
453 
454  if (!createDirectory (tempDir)) {
455  return "";
456  } else {
457  return tempDir;
458  }
459 }
460 
461 /**
462  * Creates a file if it doesn't already exist.
463  *
464  * @param file The name of the file.
465  * @return True if file is created, false otherwise.
466  */
467 bool
468 FileSystem::createFile(const std::string& file) {
469 
470  Path filePath(file);
471  string fileName = filePath.string();
472 
473  if (fileExists(file)) {
474  return true;
475  }
476 
477  if (fileIsCreatable(fileName)) {
478  FILE* f = fopen(fileName.c_str(), "w");
479  fclose(f);
480  return true;
481  } else {
482  return false;
483  }
484 }
485 
486 /**
487  * Removes a file or a directory.
488  *
489  * @param path The path of a file or a directory.
490  * @return True if directory or file is destroyed, false otherwise.
491  */
492 bool
493 FileSystem::removeFileOrDirectory(const std::string& path) {
494  if (fileExists(path)) {
495  try {
496  Path tcePath(path);
497  boost::filesystem::remove_all(tcePath);
498  return true;
499  } catch (...) {
500  // failed to destroy a file or directory
501  // probably because of lack of rights.
502  return false;
503  }
504  } else {
505  return false;
506  }
507 }
508 
509 /**
510  * Copies source file to target file.
511  *
512  * Copying can fail for the following reasons:
513  * Source file doesn't exist, source is directory, or target string is empty.
514  *
515  * If target file already exists then it's removed and source file is copied
516  * in its place. If target file is a existing directory copies the file under
517  * it without changing the files name.
518  *
519  * @param source File to be copied.
520  * @param target Target of the copy operation.
521  * @exception IOException in case the copying failed.
522  */
523 void
524 FileSystem::copy(const std::string& source, const std::string& target) {
525  namespace fs = boost::filesystem;
526  Path sourcePath(source);
527  Path targetPath(target);
528 
529  try {
530  if (fs::exists(targetPath)) {
531  if(!fileIsDirectory(target)) {
532  fs::remove(targetPath);
533  } else {
534  fs::path::iterator lastIt = --(sourcePath.end());
535  targetPath /= *lastIt;
536  // The target directory may have already a file by name
537  if(!fileIsDirectory(targetPath.string())) {
538  fs::remove(targetPath);
539  }
540  }
541  }
542  fs::copy_file(sourcePath, targetPath);
543  } catch (boost::filesystem::filesystem_error e) {
544  throw IOException(
545  __FILE__, __LINE__, __func__,
546  (boost::format(
547  "Unable to copy '%s' to '%s'") %
548  sourcePath.string() % targetPath.string()).str());
549  }
550 }
551 
552 /**
553  * Searches the given file in the given search paths and returns the
554  * absolute path to the file.
555  *
556  * @param searchPaths The search paths in priority order.
557  * @param file The file to search.
558  * @return Absolute path to the file.
559  * @exception FileNotFound If the file is not found in the search paths.
560  */
561 std::string
563  const std::vector<std::string>& searchPaths, const std::string& file) {
565 
566  if (isAbsolutePath(file)) {
567  if (fileExists(file)) {
568  return file;
569  } else {
570  string errorMsg = "File " + file + " not found.";
571  throw FileNotFound(__FILE__, __LINE__, __func__, errorMsg);
572  }
573  }
574 
575  for (vector<string>::const_iterator iter = searchPaths.begin();
576  iter != searchPaths.end(); iter++) {
577  string path = *iter;
578  string pathToFile = path + DS + file;
579  if (fileExists(pathToFile)) {
580  return absolutePathOf(pathToFile);
581  }
582  }
583 
584  string errorMsg = "File " + file + " not found in any search path.";
585  errorMsg += "Searched paths:\n";
586  for (unsigned int i = 0; i < searchPaths.size(); i++) {
587  errorMsg += searchPaths.at(i) + "\n";
588  }
589  throw FileNotFound(__FILE__, __LINE__, __func__, errorMsg);
590 }
591 
592 /**
593  * Returns the files found in the given directory.
594  *
595  * @param directory The directory.
596  * @return Vector containing the files.
597  * @exception FileNotFound If the given directory does not exist.
598  */
599 std::vector<std::string>
601  const std::string& directory, const bool absolutePaths) {
602  try {
603  std::vector<std::string> contents;
604  // default construction yields past the end
605  boost::filesystem::directory_iterator end_iter;
606 
607  if (directory != "") {
608  Path path(directory);
609  for (boost::filesystem::directory_iterator iter(path);
610  iter != end_iter; iter++) {
611  if (absolutePaths) {
612  contents.push_back(absolutePathOf(iter->path().string()));
613  } else {
614  contents.push_back(iter->path().string());
615  }
616 
617  }
618  } else {
619  for (boost::filesystem::directory_iterator iter(
620  boost::filesystem::current_path());
621  iter != end_iter; iter++) {
622  if (absolutePaths) {
623  contents.push_back(absolutePathOf(iter->path().string()));
624  } else {
625  contents.push_back(iter->path().string());
626  }
627  }
628  }
629 
630  return contents;
631 
632  } catch (const boost::filesystem::filesystem_error& e) {
633  throw FileNotFound(__FILE__, __LINE__, __func__, e.what());
634  }
635 }
636 
637 /**
638  * Returns all the sub-directories found starting from the given directory.
639  * Uses recursion to find out all the possible sub-directory levels as well.
640  *
641  * @param directory The directory where to search. Not listed in the results!
642  * @return Vector containing the sub-directories (and their sub-dirs, and...).
643  * @note This function will not search the directories containing "." !
644  * @exception FileNotFound If the given directory does not exist.
645  */
646 std::vector<std::string>
647 FileSystem::directorySubTrees(const std::string& directory) {
648  std::vector<std::string> subTrees;
649 
650  try {
651  directory_iterator end_itr;
652 
653  for (directory_iterator itr(directory); itr != end_itr; ++itr) {
654  if (is_directory(*itr) && exists(*itr) &&
655  (*itr).path().string().find(".") == string::npos) {
656  subTrees.push_back((*itr).path().string());
657 
658  std::vector<std::string> subSubTrees =
659  directorySubTrees((*itr).path().string());
660 
661  for (size_t i = 0; i < subSubTrees.size(); ++i) {
662  subTrees.push_back(subSubTrees.at(i));
663  }
664  }
665  }
666  } catch (const boost::filesystem::filesystem_error& e) {
667  throw FileNotFound(__FILE__, __LINE__, __func__, e.what());
668  }
669 
670  return subTrees;
671 }
672 
673 /**
674  * Attempts to find a file from the given directory hierarchy
675  *
676  * @param startDirectory The directory to start the search.
677  * @param fileName The filename to search for.
678  * @param pathFound A path to the found file.
679  * @return true if the file was found. Otherwise false.
680  */
681 bool
683  const Path& startDirectory,
684  const std::string& fileName,
685  Path& pathFound) {
686 
687  if (!exists(startDirectory)) {
688  return false;
689  }
690  directory_iterator end_itr;
691 
692  for (directory_iterator itr(startDirectory); itr != end_itr; ++itr) {
693  if (is_directory(*itr)) {
694  Path p((*itr).path().string());
695  if (findFileInDirectoryTree(p, fileName, pathFound))
696  return true;
697  }
698 #if BOOST_VERSION >= 103600
699  else if (itr->path().filename() == fileName)
700 #else
701  else if (itr->leaf() == fileName)
702 #endif
703  {
704  pathFound = Path((*itr).path().string());
705  return true;
706  }
707  }
708  return false;
709 }
710 
711 /**
712  * Compares two file names considering path.
713  *
714  * Compares two strings representing file names that can be with absolut or
715  * relative paths. Relative paths are interpreted against given root directory
716  * parameter.
717  *
718  * @param first File name to be compared.
719  * @param second File name to be compared.
720  * @param rootDirectory Base dir for relative paths in file names.
721  * @return True if file names are same considering path, otherwise false.
722  */
723 bool
725  const std::string& first,
726  const std::string& second,
727  const std::string& rootDirectory) {
728 
729  std::string testRootDir = rootDirectory;
730  if (rootDirectory.substr(rootDirectory.size()-1) != DIRECTORY_SEPARATOR) {
731  testRootDir += DIRECTORY_SEPARATOR;
732  }
733 
734  if (first == second) {
735  return true;
736  }
737 
738  if (FileSystem::isRelativePath(first) &&
739  FileSystem::isRelativePath(second)) {
740  return false;
741  } else if (FileSystem::isRelativePath(first)) {
742  return ((testRootDir + first) == second) ? true : false;
743  } else if (FileSystem::isRelativePath(second)) {
744  return ((testRootDir + second) == first) ? true : false;
745  }
746 
747  return false;
748 }
749 
750 /**
751  * Creates relative (to given base dir) directory.
752  *
753  * Both directories given as parameter have to be absolute or false is
754  * returned.
755  *
756  * @param baseDir string representing base directory.
757  * @param toRelDir string representing a directory which is changed to
758  * relative.
759  * @return true if toRelDir is modified as relative directory otherwise false.
760  */
761 bool
762 FileSystem::relativeDir(const std::string& baseDir, std::string& toRelDir) {
763 
764  namespace fs = boost::filesystem;
765 
766  Path basePath(baseDir);
767  Path toRelPath(toRelDir);
768 
769  fs::path::iterator dstIt = basePath.begin();
770  fs::path::iterator POIt = toRelPath.begin();
771 
772  fs::path::iterator dstEndIt = basePath.end();
773  fs::path::iterator POEndIt = toRelPath.end();
774 
775  unsigned int sameCount = 0;
776  for (; dstIt != dstEndIt && POIt != POEndIt && *dstIt == *POIt;
777  ++dstIt, ++POIt, ++sameCount) {}
778 
779  // both parameter dirs have to be absolute
780  // first path part is allways '/'
781  if (sameCount < 1) {
782  return false;
783  }
784 
785  // if the to be realtive dir is under the base dir
786  if (dstIt == dstEndIt) {
787  toRelDir.clear();
788  while (POIt != POEndIt) {
789 #if BOOST_FILESYSTEM_VERSION < 3
790  toRelDir.append(*POIt++);
791 #else
792  std::string const tmp = POIt->string();
793  toRelDir.append(tmp);
794  POIt++;
795 #endif
796  if (POIt != POEndIt) {
797  toRelDir.append(DIRECTORY_SEPARATOR);
798  }
799  }
800  return true;
801  } else { // if above
802  std::string temp;
803  while (POIt != POEndIt) {
804 #if BOOST_FILESYSTEM_VERSION < 3
805  temp.append(*POIt++);
806 #else
807  std::string const tmp = POIt->string();
808  POIt++;
809  temp.append(tmp);
810 #endif
811  if (POIt != POEndIt) {
812  temp.append(DIRECTORY_SEPARATOR);
813  }
814  }
815 
816  unsigned int diffCount = 0;
817  for (; dstIt != dstEndIt; ++dstIt, ++diffCount) {
818  }
819 
820  toRelDir.clear();
821  for (unsigned int i = 0; diffCount > i; ++i) {
822  toRelDir.append("..");
823  toRelDir.append(DIRECTORY_SEPARATOR);
824  }
825  toRelDir.append(temp);
826  }
827 
828  return true;
829 }
830 
831 /**
832  * Creates relative path out of provided base path.
833  *
834  * A relative path is returned if it is found under any of the search paths.
835  * Example: if base path is "/usr/foo/bar/x.hdb" and provided search path
836  * is "/usr/foo", the following relative path is formed: "bar/x.hdb".
837  *
838  * @param searchPaths Relative path to base path is searched under these.
839  * @param basePath Path that needs to be changed into a relative path.
840  * @param toRelPath Outputs possibly created relative path.
841  * @return True if a relative path was created out of base path.
842  */
843 bool
845  const std::vector<std::string>& searchPaths,
846  const std::string& basePath,
847  std::string& toRelPath) {
848 
849  if (!isAbsolutePath(basePath)) {
850  return false;
851  }
852 
853  for (unsigned int i = 0; i < searchPaths.size(); ++i) {
854  string searchPath = searchPaths.at(i);
855  string relativePath = basePath;
856 
857  // try to find a relative path to the base path under search path
858  if (relativeDir(searchPath, relativePath)) {
859  string fullPath = searchPath + DIRECTORY_SEPARATOR + relativePath;
860 
861  // special case: if provided search path was same as base path
862  if (relativePath == "") {
863  toRelPath = relativePath;
864  return true;
865  } else if (isRelativePath(relativePath) && fileExists(fullPath)) {
866  if (fullPath.length() == basePath.length()) {
867  toRelPath = relativePath;
868  return true;
869  }
870  }
871  }
872  }
873 
874  return false;
875 }
876 
877 /**
878  * Reads a block of text from a file.
879  *
880  * Start and end of the block are found by matching given regular expressions
881  * against whole lines in source file.
882  *
883  * @param sourceFile File that is read.
884  * @param blockStartRE Regex that matches beginning of the block (one whole
885  * line) that is going to be read from the source file.
886  * @param blockEndRE Regex that matches end of the block (one whole line) that
887  * is going to be read from the source file.
888  * @param readBlock Parameter where the read block is to be stored.
889  * @param includeMatchingLines Include lines that mark the borders of the
890  * block (lines that matched given regular expressions) to the block.
891  * @return True if something was stored to readBlock string, otherwise false.
892  */
893 bool
895  const std::string& sourceFile,
896  const std::string& blockStartRE, //reads from file beginning by default
897  const std::string& blockEndRE, // reads to file end by default
898  std::string& readBlock,
899  const bool includeMatchingLines) { //true by default
900 
901  const int LINESIZE = 256;
902  char line[LINESIZE];
903 
904  const boost::regex reStart(blockStartRE,
905  boost::regex::perl|boost::regex::icase);
906  const boost::regex reEnd(blockEndRE,
907  boost::regex::perl|boost::regex::icase);
908 
909  string::const_iterator begin;
910  string::const_iterator end;
911  string stemp;
912  std::ifstream ifs(sourceFile.c_str(), std::ifstream::in);
913  boost::match_results<string::const_iterator> matches;
914  bool outsideBlock = true;
915  while (ifs.good()) {
916 
917  ifs.getline(line, LINESIZE-1);
918  stemp = string(line);
919  begin = stemp.begin();
920  end = stemp.end();
921 
922  // test if found block border
923  if (boost::regex_search(begin, end, outsideBlock ? reStart : reEnd)) {
924  if (includeMatchingLines) {
925  readBlock.append(stemp + "\n");
926  }
927  if (!outsideBlock) {
928  break;
929  } else {
930  outsideBlock = false;
931  }
932  } else if (!outsideBlock) { // if inside block
933  readBlock.append(stemp + "\n");
934  }
935  }
936 
937  ifs.close();
938 
939  return ifs.good();
940 }
941 
942 /**
943  * Appends to specified place in file, can replace a section.
944  *
945  * Doesn't use temp files so uses lot of memory for big files.
946  *
947  * @param targetFile File to be edited.
948  * @param ARStartRE Regex that matches the line where appending starts.
949  * @param writeToFile String that is written to the file.
950  * @param AREndRE Regex that matches last line that is replaced or deleted if
951  * writeToFile string contains less lines than is between start and end
952  * matches.
953  * @param discardBlockBorder If true Regex matching lines are replaced or deleted.
954  *
955  * @return True if something was writen to the file, otherwise false.
956  */
957 bool
959  const std::string& targetFile,
960  const std::string& ARStartRE,
961  const std::string& writeToFile,
962  const std::string& AREndRE,
963  const bool discardBlockBorder) {
964 
965  const int LINESIZE = 1000;
966  char line[LINESIZE];
967 
968  const boost::regex reStart(ARStartRE,
969  boost::regex::perl|boost::regex::icase);
970  boost::regex reEnd;
971  if (!AREndRE.empty()) {
972  reEnd = boost::regex(AREndRE, boost::regex::perl|boost::regex::icase);
973  }
974  boost::regex re = reStart;
975 
976  string::const_iterator begin;
977  string::const_iterator end;
978  string stemp = "";
979  string endFile = "";
980  int blockStartPos = -1;
981  std::fstream fs(targetFile.c_str(), std::fstream::in | std::fstream::out);
982  boost::match_results<string::const_iterator> matches;
983 
984  bool beforeBlock = true;
985  bool afterBlock = false;
986  while (fs.good()) {
987 
988  fs.getline(line, LINESIZE-1);
989 
990  if (fs.eof()) {
991  if (blockStartPos != -1) {
992  fs.clear();
993  fs.seekp(blockStartPos);
994  fs.seekg(blockStartPos);
995  } else {
996  // no place of appending was found, ARStartRE didn't match any
997  // line
998  fs.close();
999  return false;
1000  }
1001 
1002  if (!fs.good()) {
1003  fs.close();
1004  return false;
1005  }
1006 
1007  fs.write(writeToFile.c_str(), writeToFile.length());
1008  fs.write(endFile.c_str(), endFile.length());
1009 
1010  if (truncate(targetFile.c_str(), fs.tellp()) != 0) {
1011  abortWithError("truncate failed!");
1012  }
1013 
1014  break;
1015  }
1016 
1017  stemp = string(line);
1018  begin = stemp.begin();
1019  end = stemp.end();
1020 
1021  // test if found block border
1022  if (!afterBlock && boost::regex_search(begin, end, re)) {
1023  if (beforeBlock) {
1024  // to inside replace block
1025  beforeBlock = false;
1026  // if no replace block end then no searching for it
1027  afterBlock = AREndRE.empty() ? true : afterBlock;
1028 
1029  if (discardBlockBorder) {
1030  blockStartPos = static_cast<int>(fs.tellg()) -
1031  static_cast<int>(fs.gcount());
1032  } else {
1033  blockStartPos = fs.tellg();
1034  }
1035  re = reEnd;
1036  } else {
1037  // to outside replace block
1038  if (!discardBlockBorder) {
1039  endFile.append(stemp + "\n");
1040  }
1041  afterBlock = true;
1042  }
1043  } else if (afterBlock) {
1044  // outside replace block
1045  endFile.append(stemp + "\n");
1046  }
1047  }
1048 
1049  fs.close();
1050  return true;
1051 }
1052 
1053 /**
1054  * Counts lines in a file.
1055  *
1056  * @param filepath Path to the file.
1057  * @return The count if successful. On error returns negative number.
1058  */
1059 int
1060 FileSystem::countLines(const std::string& filepath) {
1061  std::ifstream fileStream(filepath);
1062  if (!fileStream.is_open()) {
1063  return -1;
1064  }
1065  unsigned count = 0;
1066  std::string dummyLine;
1067  while (std::getline(fileStream, dummyLine)) {
1068  count++;
1069  }
1070  return count;
1071 }
1072 
1073 //////////////////////////////////////////////////////////////////////////////
1074 // Path
1075 //////////////////////////////////////////////////////////////////////////////
1076 
1077 /**
1078  * Constructs an empty Path.
1079  */
1080 Path::Path() : boost::filesystem::path() {
1081 }
1082 
1083 /**
1084  * Constructor for implicit conversion from boost::filesystem::path.
1085  */
1086 Path::Path(const boost::filesystem::path& path) :
1087  boost::filesystem::path(path) {
1088 }
1089 
1090 /**
1091  * Destructor.
1092  */
1094 }
1095 
1096 /**
1097  * Copy constructor.
1098  */
1099 Path&
1100 Path::operator=(const boost::filesystem::path& pathName) {
1101  if (this == &pathName) {
1102  return *this;
1103  }
1104 
1105  boost::filesystem::path::assign(
1106  pathName.string().begin(), pathName.string().end());
1107  return *this;
1108 }
1109 
1110 /**
1111  * Allows conversion to std::string.
1112  */
1113 Path::operator std::string() const {
1114  return this->string();
1115 }
1116 
1117 /**
1118  * Allows conversion to TCEString.
1119  */
1120 Path::operator TCEString() const {
1121  return this->string();
1122 }
1123 
1124 /**
1125  * Returns C string of the path.
1126  */
1127 const char*
1128 Path::c_str() const {
1129  return this->string().c_str();
1130 }
1131 
1132 /**
1133  * Appends file of directory to the path.
1134  */
1135 Path operator/(const Path& path, const std::string& fileOrDir) {
1136  return Path(boost::filesystem::operator/(path, fileOrDir));
1137 }
Path
Definition: FileSystem.hh:197
POP_CLANG_DIAGS
#define POP_CLANG_DIAGS
Definition: CompilerWarnings.hh:96
FileSystem.hh
FileSystem::removeFileOrDirectory
static bool removeFileOrDirectory(const std::string &path)
Definition: FileSystem.cc:493
FileNotFound
Definition: Exception.hh:224
FileSystem::createDirectory
static bool createDirectory(const std::string &path)
Definition: FileSystem.cc:400
FileSystem::setFileExecutable
static bool setFileExecutable(const std::string fileName)
Definition: FileSystem.cc:322
Application::writeToErrorLog
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
Definition: Application.cc:224
IGNORE_CLANG_WARNING
#define IGNORE_CLANG_WARNING(X)
Definition: CompilerWarnings.hh:85
FileSystem::isRelativePath
static bool isRelativePath(const std::string &pathName)
Definition: FileSystem.cc:252
FileSystem::directorySubTrees
static std::vector< std::string > directorySubTrees(const std::string &directory)
Definition: FileSystem.cc:647
boost
Definition: BoostGraph.hh:46
FileSystem::globPath
static void globPath(const std::string &pattern, std::vector< std::string > &filenames)
Definition: FileSystem.cc:197
FileSystem::absolutePathOf
static std::string absolutePathOf(const std::string &pathName)
Definition: FileSystem.cc:303
FileSystem::relativeDir
static bool relativeDir(const std::string &baseDir, std::string &toRelDir)
Definition: FileSystem.cc:762
FileSystem::fileOfPath
static std::string fileOfPath(const std::string pathName)
Definition: FileSystem.cc:101
Path::~Path
virtual ~Path()
Definition: FileSystem.cc:1093
FileSystem::fileIsCreatable
static bool fileIsCreatable(const std::string fileName)
Definition: FileSystem.cc:123
MathTools::random
static int random(int, int)
assert
#define assert(condition)
Definition: Application.hh:86
Path::c_str
const char * c_str() const
Definition: FileSystem.cc:1128
FileSystem::makeRelativePath
static bool makeRelativePath(const std::vector< std::string > &searchPaths, const std::string &basePath, std::string &toRelPath)
Definition: FileSystem.cc:844
FileSystem::homeDirectory
static std::string homeDirectory()
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
Path::Path
Path()
Definition: FileSystem.cc:1080
FileSystem::lastModificationTime
static std::time_t lastModificationTime(const std::string &filePath)
Definition: FileSystem.cc:352
FileSystem::fileExtension
static std::string fileExtension(const std::string &fileName)
Definition: FileSystem.cc:279
__func__
#define __func__
Definition: Application.hh:67
FileSystem::directoryOfPath
static std::string directoryOfPath(const std::string fileName)
Definition: FileSystem.cc:79
FileSystem::copy
static void copy(const std::string &source, const std::string &target)
Definition: FileSystem.cc:524
FileSystem::isPath
static bool isPath(const std::string &pathName)
Definition: FileSystem.cc:265
FileSystem::expandTilde
static std::string expandTilde(const std::string &stringWithTilde)
Definition: FileSystem.cc:217
FileSystem::sizeInBytes
static uintmax_t sizeInBytes(const std::string &filePath)
Definition: FileSystem.cc:376
FileSystem::createFile
static bool createFile(const std::string &file)
Definition: FileSystem.cc:468
FileSystem::readBlockFromFile
static bool readBlockFromFile(const std::string &sourceFile, const std::string &blockStartRE, const std::string &blockEndRE, std::string &readBlock, const bool includeMatchingLines=true)
Definition: FileSystem.cc:894
FileSystem::DIRECTORY_SEPARATOR
static const std::string DIRECTORY_SEPARATOR
Definition: FileSystem.hh:189
FileSystem::CURRENT_DIRECTORY
static const std::string CURRENT_DIRECTORY
Definition: FileSystem.hh:190
FileSystem::changeWorkingDir
static bool changeWorkingDir(const std::string &path)
Definition: FileSystem.cc:185
Path::operator=
Path & operator=(const boost::filesystem::path &pathName)
Definition: FileSystem.cc:1100
FileSystem::countLines
static int countLines(const std::string &filepath)
Definition: FileSystem.cc:1060
FileSystem::appendReplaceFile
static bool appendReplaceFile(const std::string &targetFile, const std::string &ARStartRE, const std::string &writeToFile, const std::string &AREndRE="", const bool discardBlockBorder="true")
Definition: FileSystem.cc:958
TCEString
Definition: TCEString.hh:53
operator/
Path operator/(const Path &path, const std::string &fileOrDir)
Definition: FileSystem.cc:1135
FileSystem::currentWorkingDir
static std::string currentWorkingDir()
Definition: FileSystem.cc:142
FileSystem::STRING_WILD_CARD
static const std::string STRING_WILD_CARD
Definition: FileSystem.hh:191
IOException
Definition: Exception.hh:130
MathTools.hh
DS
#define DS
Definition: LLVMBackend.cc:124
FileSystem::fileNameBody
static std::string fileNameBody(const std::string &fileName)
Definition: FileSystem.cc:291
FileSystem::findFileInSearchPaths
static std::string findFileInSearchPaths(const std::vector< std::string > &searchPaths, const std::string &file)
Definition: FileSystem.cc:562
FileSystem::compareFileNames
static bool compareFileNames(const std::string &first, const std::string &second, const std::string &rootDirectory)
Definition: FileSystem.cc:724
FileSystem::isAbsolutePath
static bool isAbsolutePath(const std::string &pathName)
Definition: FileSystem.cc:234
FileSystem::createTempDirectory
static std::string createTempDirectory(const std::string &path="/tmp", const std::string &tempDirPrefix="tmp_tce_")
Definition: FileSystem.cc:441
CompilerWarnings.hh
FileSystem::directoryContents
static std::vector< std::string > directoryContents(const std::string &directory, const bool absolutePaths=true)
Definition: FileSystem.cc:600
FileSystem::findFileInDirectoryTree
static bool findFileInDirectoryTree(const Path &startDirectory, const std::string &fileName, Path &pathFound)
Definition: FileSystem.cc:682