OpenASIP 2.2
Loading...
Searching...
No Matches
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"
53IGNORE_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
61using std::string;
62using std::vector;
63
64const std::string FileSystem::DIRECTORY_SEPARATOR =
65string(DIR_SEPARATOR);
66const std::string FileSystem::CURRENT_DIRECTORY = ".";
67const std::string FileSystem::STRING_WILD_CARD = "*";
68
69using 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 */
78std::string
79FileSystem::directoryOfPath(const std::string fileName) {
80
81 Path origString(fileName);
82 string file = origString.string();
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 */
100std::string
101FileSystem::fileOfPath(const std::string pathName) {
102 if (!isPath(pathName)) {
103 return pathName;
104 }
105 Path origString(pathName);
106 string path = origString.string();
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 */
122bool
123FileSystem::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 */
141std::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 */
184bool
185FileSystem::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 */
196void
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 */
216string
217FileSystem::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 */
233bool
234FileSystem::isAbsolutePath(const std::string& pathName) {
235 Path path(pathName);
236 string pathString = path.string();
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 */
251bool
252FileSystem::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 */
264bool
265FileSystem::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 */
278string
279FileSystem::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 */
290string
291FileSystem::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 */
302string
303FileSystem::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 */
321bool
322FileSystem::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 */
351std::time_t
352FileSystem::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 */
375uintmax_t
376FileSystem::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 */
399bool
400FileSystem::createDirectory(const std::string& path) {
401 std::string p = path;
402 if (!isAbsolutePath(p)) {
403 p = absolutePathOf(p);
404 }
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 */
440std::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 */
467bool
468FileSystem::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 */
492bool
493FileSystem::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 */
523void
524FileSystem::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 const& 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 */
561std::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 */
599std::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 */
646std::vector<std::string>
647FileSystem::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 */
681bool
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 */
723bool
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) &&
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 */
761bool
762FileSystem::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 */
843bool
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 */
893bool
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 */
957bool
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 */
1059int
1060FileSystem::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 */
1080Path::Path() : boost::filesystem::path() {
1081}
1082
1083/**
1084 * Constructor for implicit conversion from boost::filesystem::path.
1085 */
1086Path::Path(const boost::filesystem::path& path) :
1087 boost::filesystem::path(path) {
1088}
1089
1090/**
1091 * Destructor.
1092 */
1094}
1095
1096/**
1097 * Copy constructor.
1098 */
1099Path&
1100Path::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 */
1113Path::operator std::string() const {
1114 return this->string();
1115}
1116
1117/**
1118 * Allows conversion to TCEString.
1119 */
1120Path::operator TCEString() const {
1121 return this->string();
1122}
1123
1124/**
1125 * Returns C string of the path.
1126 */
1127const char*
1129 return this->string().c_str();
1130}
1131
1132/**
1133 * Appends file of directory to the path.
1134 */
1135Path operator/(const Path& path, const std::string& fileOrDir) {
1136 return Path(boost::filesystem::operator/(path, fileOrDir));
1137}
#define __func__
#define abortWithError(message)
#define assert(condition)
#define POP_CLANG_DIAGS
#define IGNORE_CLANG_WARNING(X)
Path operator/(const Path &path, const std::string &fileOrDir)
#define DS
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
static std::string homeDirectory()
static bool createFile(const std::string &file)
static bool isRelativePath(const std::string &pathName)
static bool findFileInDirectoryTree(const Path &startDirectory, const std::string &fileName, Path &pathFound)
static std::string absolutePathOf(const std::string &pathName)
static bool isAbsolutePath(const std::string &pathName)
static bool readBlockFromFile(const std::string &sourceFile, const std::string &blockStartRE, const std::string &blockEndRE, std::string &readBlock, const bool includeMatchingLines=true)
static bool appendReplaceFile(const std::string &targetFile, const std::string &ARStartRE, const std::string &writeToFile, const std::string &AREndRE="", const bool discardBlockBorder="true")
static void globPath(const std::string &pattern, std::vector< std::string > &filenames)
static bool fileIsReadable(const std::string fileName)
static bool createDirectory(const std::string &path)
static uintmax_t sizeInBytes(const std::string &filePath)
static bool removeFileOrDirectory(const std::string &path)
static bool changeWorkingDir(const std::string &path)
static const std::string DIRECTORY_SEPARATOR
static std::time_t lastModificationTime(const std::string &filePath)
static std::string createTempDirectory(const std::string &path="/tmp", const std::string &tempDirPrefix="tmp_tce_")
static std::string fileNameBody(const std::string &fileName)
static std::vector< std::string > directoryContents(const std::string &directory, const bool absolutePaths=true)
static std::string fileOfPath(const std::string pathName)
static bool compareFileNames(const std::string &first, const std::string &second, const std::string &rootDirectory)
static const std::string CURRENT_DIRECTORY
static void copy(const std::string &source, const std::string &target)
static std::string directoryOfPath(const std::string fileName)
Definition FileSystem.cc:79
static std::string fileExtension(const std::string &fileName)
static std::string currentWorkingDir()
static std::string findFileInSearchPaths(const std::vector< std::string > &searchPaths, const std::string &file)
static const std::string STRING_WILD_CARD
static bool fileIsDirectory(const std::string fileName)
static bool setFileExecutable(const std::string fileName)
static bool relativeDir(const std::string &baseDir, std::string &toRelDir)
static std::vector< std::string > directorySubTrees(const std::string &directory)
static bool makeRelativePath(const std::vector< std::string > &searchPaths, const std::string &basePath, std::string &toRelPath)
static bool fileIsWritable(const std::string fileName)
static bool isPath(const std::string &pathName)
static int countLines(const std::string &filepath)
static bool fileIsCreatable(const std::string fileName)
static bool fileExists(const std::string fileName)
static std::string expandTilde(const std::string &stringWithTilde)
static int random(int, int)
virtual ~Path()
Path & operator=(const boost::filesystem::path &pathName)
const char * c_str() const
operator std::string() const