1 ///////////////////////////////////////////////////////////////////////////
2 // Workfile: FSHelper.cxx
3 // Author: Daniel Giritzer <daniel@giritzer.eu>
5 // Description: Diese Klasse stellt plattformunabhängige funktionen auf das
6 // Dateisystem zur verfügung. Bei fehler werden exeptions
7 // des Typs std::string geworfen.
9 ///////////////////////////////////////////////////////////////////////////
13 #include <sys/types.h>
14 #include <FL/fl_utf8.h>
25 std::vector<FSHelper::File> FSHelper::listFiles(const std::string &src)
27 std::vector<File> retVal;
31 if((dir = opendir(src.c_str())) != nullptr)
33 while((ent = readdir(dir)) != nullptr)
36 curFile.first = addDirLastSlash(std::string(src));
37 curFile.second = std::string(ent->d_name);
38 retVal.push_back(curFile);
43 throw std::string("Directory could not be opened: " + src);
48 void FSHelper::copyFile(const std::string &src, const std::string &dest)
50 std::ifstream srcStream(src, std::ios::in | std::ios_base::binary);
53 throw std::string("Failed to open input file: " + src);
55 std::ofstream destStream(dest, std::ios::out |std::ios_base::binary);
57 if(!destStream.good())
58 throw std::string("Failed to open output file: " + dest);
60 destStream << srcStream.rdbuf();
67 void FSHelper::makeDir(const std::string &dir)
70 if(fl_mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0)
71 throw std::string("Failed to create directory: " + dir);
75 void FSHelper::createFile(const std::string &path)
77 std::ofstream file(path, std::ios::out);
80 throw std::string("Failed to create file: " + path);
85 void FSHelper::removeFile(const std::string &path)
93 void FSHelper::copyDir(const std::string &src, const std::string &dest)
95 std::string from = addDirLastSlash(src);
96 std::string to = addDirLastSlash(dest);
98 if(!dirExists(addDirLastSlash(from)))
99 throw std::string("Source folder does not exist: " + from);
105 catch(std::string& e)
107 throw std::string("Could not create destination folder: " + to);
110 std::vector<File> files;
111 if(!listFilesRecursive(from, files, true))
112 throw std::string("Could not fetch source folder content: " + from);
114 std::vector<std::string> folders;
115 if(!listDirsRecursive(from, folders, true))
116 throw std::string("Could not fetch source folder directory tree: " + from);
118 // Erstelle Ordnerbaum
119 for(auto folder : folders)
121 folder.replace(folder.find(from), from.length(), to);
124 makeDir(addDirLastSlash(folder));
126 catch(std::string& e)
128 throw std::string("Could not create directory tree in destination directory! Failed on: " + folder);
134 for(auto inFile : files)
136 File outFile = inFile;
137 // ersetze Qellordner mit zielordner
138 outFile.first.replace(outFile.first.find(from), from.length(), to);
141 makeDir(addDirLastSlash(outFile.first));
143 catch(std::string& e)
145 throw std::string("Could not create subfolder in destination directory! Failed on: " + outFile.first);
150 copyFile(inFile.first + inFile.second, outFile.first + outFile.second);
152 catch(std::string& e)
154 throw std::string("Could not copy file: " + inFile.first + inFile.second);
161 bool FSHelper::validFileName(const std::string &fName)
163 char invalidChars[] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '~', '`', ' ', '\\',
164 ';', ':', '+', '=', '*', '/', '<', '>', '?', ',', '[', ']', '{', '}'
167 unsigned int pos = fName.find_first_of(invalidChars, 0, sizeof(invalidChars));
168 if (pos != std::string::npos)
174 bool FSHelper::dirExists(const std::string &directory)
176 std::string dir = rmDirLastSlash(directory);
178 // überprüfe existenz
180 if( fl_stat( dir.c_str(), &info ) != 0 )
182 if( info.st_mode & S_IFDIR )
188 bool FSHelper::fileExists(const std::string &file)
190 std::ifstream f(file);
191 bool retVal = f.good();
196 std::string FSHelper::addDirLastSlash(const std::string &dir)
198 if(dir.back() != '\\' && dir.back() != '/')
208 std::string FSHelper::rmDirLastSlash(const std::string &dir)
210 if(dir.back() == '\\' || dir.back() == '/')
211 return dir.substr(0, dir.size()-1);
216 bool FSHelper::listFilesRecursive(const std::string& path, std::vector<FSHelper::File>& files,const bool showHiddenDirs)
218 std::string dir = addDirLastSlash(path);
221 dpdf = opendir(dir.c_str());
224 while((epdf = readdir(dpdf)) != nullptr)
229 if(stat((dir + std::string(epdf->d_name)).c_str(), &s) < 0)
232 if(S_ISREG(s.st_mode))
236 curFile.first = std::string(addDirLastSlash(dir));
237 curFile.second = std::string(epdf->d_name);
238 files.push_back(curFile);
240 else if(showHiddenDirs ? (S_ISDIR(s.st_mode) && std::string(epdf->d_name) != ".." && std::string(epdf->d_name) != "." ) :
241 (S_ISDIR(s.st_mode) && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ))
243 listFilesRecursive(dir+epdf->d_name,files, showHiddenDirs);
252 bool FSHelper::listDirsRecursive(const std::string &path, std::vector<std::string> &folders,const bool showHiddenDirs)
254 std::string dir = addDirLastSlash(path);
257 dpdf = opendir(dir.c_str());
260 while((epdf = readdir(dpdf)) != nullptr)
264 if(stat((dir + std::string(epdf->d_name)).c_str(), &s) < 0)
267 else if(showHiddenDirs ? (S_ISDIR(s.st_mode) && std::string(epdf->d_name) != ".." && std::string(epdf->d_name) != "." ) :
268 (S_ISDIR(s.st_mode) && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ))
270 if(!(std::find(folders.begin(), folders.end(), dir+epdf->d_name) != folders.end()))
271 folders.push_back(addDirLastSlash(dir+epdf->d_name));
272 listDirsRecursive(dir+epdf->d_name,folders, showHiddenDirs);
280 std::vector<std::string> FSHelper::listDirsNonRecursive(const std::string &path,const bool showHiddenDirs)
282 std::vector<std::string> folders;
283 std::string dir = addDirLastSlash(path);
286 dpdf = opendir(dir.c_str());
289 while((epdf = readdir(dpdf)) != nullptr)
293 stat((dir + std::string(epdf->d_name)).c_str(), &s);
294 if(showHiddenDirs ? (S_ISDIR(s.st_mode) && std::string(epdf->d_name) != ".." && std::string(epdf->d_name) != "." ) :
295 (S_ISDIR(s.st_mode) && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ))
297 if(!(std::find(folders.begin(), folders.end(), dir+epdf->d_name) != folders.end()))
298 folders.push_back(addDirLastSlash(dir+epdf->d_name));
306 std::string FSHelper::getCurrentWorkingDir()
310 if(fl_getcwd(temp, PATH_MAX))
312 return convertPathToWindows(temp);
314 return convertPathToUnix(temp);
317 // leerer string bei fehler
318 return std::string("");
321 std::string FSHelper::convertPathToWindows(const std::string &dir)
323 std::string retDir = dir;
324 std::replace(retDir.begin(), retDir.end(), '/', '\\');
328 std::string FSHelper::convertPathToUnix(const std::string &dir)
330 std::string retDir = dir;
331 std::replace(retDir.begin(), retDir.end(), '\\', '/');
335 std::string FSHelper::findExecutableInPath(const std::string &executable)
337 std::string path = getenv("PATH");
345 std::vector<std::string> tokens;
347 std::istringstream tokenStream(path);
348 while (std::getline(tokenStream, token, delim))
350 if(fileExists(addDirLastSlash(token) + executable))
351 return addDirLastSlash(token) + executable;
353 if(fileExists(addDirLastSlash(token) + executable + ".exe"))
354 return addDirLastSlash(token) + executable + ".exe";
356 throw std::string("Executable not found in PATH!: " + executable);
359 std::string FSHelper::getFileName(const std::string &file)
361 std::string retFile = "";
362 unsigned int ind = file.find_last_of("/");
363 if(ind != std::string::npos)
364 retFile = file.substr(ind + 1, file.size());
366 ind = file.find_last_of("\\");
367 if(ind != std::string::npos)
368 retFile = file.substr(ind + 1, file.size());
373 std::string FSHelper::getPath(const std::string &file)
375 std::string retFile = "";
376 unsigned int ind = file.find_last_of("/");
377 if(ind != std::string::npos)
378 retFile = file.substr(0, ind + 1);
380 ind = file.find_last_of("\\");
381 if(ind != std::string::npos)
382 retFile = file.substr(0, ind + 1);
387 void FSHelper::executeCommand(const std::string &path, const std::string &command, std::vector<std::string> params,const std::string &log)
390 if((!path.empty()) && !dirExists(path))
391 throw std::string("Path does not exist: " + path);
393 std::string execCommand = findExecutableInPath(command);
395 if(!log.empty() && !fileExists(log))
400 std::string paramString;
402 for(auto curParam : params)
403 paramString = curParam + " ";
406 paramString = paramString + " >> " + log;
408 // Benutze System, da CreateProcess nicht POSIX standardkonform ist
411 // Laufwerkbuchstaben ermitteln
412 unsigned int ind = path.find_first_of(":");
413 if(ind == std::string::npos)
414 throw std::string("Illegal Path! Path does not cointain drive letter! :" + path);
416 std::string driveLetter = path.substr(0, ind+1);
417 system(std::string(driveLetter + " && cd " + path + " && " + execCommand + " " + paramString).c_str());
420 system(std::string(execCommand + " " + paramString).c_str());
422 // String vector zu char array
423 std::vector<char*> charParams;
425 // Param Array muss wie folgt aufgebaut sein:
431 // Falls DynLoader gesetzt ist dynloader erster parameter
432 // im array (weil command)
433 if(!mLinuxDynLoader.empty())
435 char *pc = new char[mLinuxDynLoader.size()+1];
436 std::strcpy(pc, mLinuxDynLoader.c_str());
437 charParams.emplace_back(pc);
438 execCommand = mLinuxDynLoader; //Auszuführender befehl ist dynloader, kommando
439 //ist dann erster parameter (= zweites element im array)
443 char *pc = new char[findExecutableInPath(command).size()+1];
444 std::strcpy(pc, findExecutableInPath(command).c_str());
445 charParams.emplace_back(pc);
447 // param vector zu char array convertieren
448 std::transform(params.begin(), params.end(), std::back_inserter(charParams),
449 [](const std::string & s)
452 char *pc = new char[s.size()+1];
453 std::strcpy(pc, s.c_str());
457 charParams.emplace_back(nullptr); //Letztes element muss ein nullpointer sein
466 std::exit(EXIT_FAILURE);
471 if(chdir(path.c_str())!=0)
472 std::exit(EXIT_FAILURE);
474 execvp(execCommand.c_str(), &charParams[0]);
476 // bei fehler Char array im Child freigeben
477 for(auto curParam : charParams)
480 // Soll nicht erreicht werden. Falls ja
481 // Child prozess beenden
482 std::exit(EXIT_FAILURE);
493 // Char array freigeben
494 for(auto curParam : charParams)
497 // Logfile schliessen
500 if(!WIFEXITED(status))
501 throw std::string("Could not execute command: " + command);
506 void FSHelper::setLinuxDynLoader(const std::string &Loader)
509 if(!fileExists(Loader))
510 throw std::string("Specified Loader does not exist: " + Loader);
513 mLinuxDynLoader = Loader;
517 std::string FSHelper::getLinuxDynLoader()
519 return mLinuxDynLoader;
523 void FSHelper::removeLinuxDynLoader()
525 mLinuxDynLoader.clear();