filetools.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #define _FILE_OFFSET_BITS 64
  2. #include <stdio.h>
  3. #include <sys/file.h>
  4. #include <sys/stat.h>
  5. #include <dirent.h>
  6. #include <unistd.h>
  7. #include <cstring>
  8. #include <iostream>
  9. #include <fstream>
  10. #include "Exception.h"
  11. #include "filetools.h"
  12. std::string concatPathAndFilename(const std::string& path, const std::string& filename)
  13. {
  14. std::string result = path;
  15. if (result[result.length() - 1] != '/')
  16. result += "/";
  17. result += filename;
  18. return result;
  19. }
  20. void fileList(const std::string& fn,
  21. std::vector<std::string>& file, bool recursive)
  22. {
  23. struct stat fstat;
  24. if (stat(fn.c_str(), &fstat) != 0)
  25. return;
  26. if (S_ISREG(fstat.st_mode))
  27. file.push_back(fn);
  28. else if (S_ISDIR(fstat.st_mode))
  29. {
  30. struct dirent* dp;
  31. DIR* dir;
  32. if ((dir = opendir(fn.c_str())) != NULL)
  33. {
  34. /* Loop through directory entries. */
  35. while ((dp = readdir(dir)) != NULL)
  36. {
  37. std::string fname = dp->d_name;
  38. std::string pname = concatPathAndFilename(fn, fname);
  39. if (stat(pname.c_str(), &fstat) == 0)
  40. {
  41. if (S_ISDIR(fstat.st_mode))
  42. {
  43. if (recursive)
  44. if (fname != "." && fname != "..")
  45. fileList(pname, file, true);
  46. }
  47. else if (S_ISREG(fstat.st_mode))
  48. file.push_back(pname);
  49. }
  50. }
  51. closedir(dir);
  52. }
  53. }
  54. }
  55. void dirList(const std::string& fn,
  56. std::vector<std::string>& file, bool recursive)
  57. {
  58. struct stat fstat;
  59. if (stat(fn.c_str(), &fstat) != 0)
  60. return;
  61. if (S_ISREG(fstat.st_mode))
  62. file.push_back(fn);
  63. else if (S_ISDIR(fstat.st_mode))
  64. {
  65. struct dirent* dp;
  66. DIR* dir;
  67. if ((dir = opendir(fn.c_str())) != NULL)
  68. {
  69. /* Loop through directory entries. */
  70. while ((dp = readdir(dir)) != NULL)
  71. {
  72. std::string fname = dp->d_name;
  73. std::string pname = concatPathAndFilename(fn, fname);
  74. if (stat(pname.c_str(), &fstat) == 0)
  75. {
  76. if (S_ISDIR(fstat.st_mode))
  77. {
  78. if (fname != "." && fname != "..")
  79. {
  80. file.push_back(pname);
  81. if (recursive)
  82. dirList(pname, file, true);
  83. }
  84. }
  85. }
  86. }
  87. closedir(dir);
  88. }
  89. }
  90. }
  91. void fileList(int argc, char** argv,
  92. int optind, std::vector<std::string>& file, bool recursive)
  93. {
  94. for (int i = optind; i < argc; i++)
  95. fileList(argv[i], file, recursive);
  96. }
  97. void strings2File(const std::vector<std::string>& s, const std::string& fn)
  98. {
  99. std::ofstream os(fn);
  100. if (!os.good())
  101. throw Exception("strings to file", "Cannot open file " + fn);
  102. for (std::string t : s)
  103. os << t << std::endl;
  104. os.close();
  105. }
  106. void file2Strings(const std::string& fn, std::vector<std::string>& s)
  107. {
  108. std::ifstream is(fn);
  109. if (!is.good())
  110. throw Exception("file to strings", "Cannot open file " + fn);
  111. std::string input;
  112. while (getline(is, input))
  113. s.push_back(input);
  114. }
  115. bool fileExists(const std::string& name)
  116. {
  117. struct stat fstat;
  118. if (stat(name.c_str(), &fstat) != 0)
  119. return false;
  120. if (!S_ISREG(fstat.st_mode))
  121. return false;
  122. return true;
  123. }
  124. bool dirExists(const std::string& name)
  125. {
  126. struct stat fstat;
  127. if (stat(name.c_str(), &fstat) != 0)
  128. return false;
  129. if (!S_ISDIR(fstat.st_mode))
  130. return false;
  131. return true;
  132. }
  133. int lock_fd;
  134. void createLock(const std::string& lockfilename)
  135. {
  136. lock_fd = open(lockfilename.c_str(), O_RDWR | O_CREAT, 0666); // open or create lockfile
  137. //check open success...
  138. int rc = flock(lock_fd, LOCK_EX | LOCK_NB); // grab exclusive lock, fail if can't obtain.
  139. if (rc)
  140. {
  141. std::cerr << "ERROR: cannot get lock at " + lockfilename << std::endl;
  142. exit(1);
  143. // no exception, because at normal end of program lock is
  144. // unlocked and removed
  145. }
  146. }
  147. void removeLock(const std::string& lockfilename)
  148. {
  149. flock(lock_fd, LOCK_UN);
  150. unlink(lockfilename.c_str());
  151. }
  152. int removeDir(const std::string& path)
  153. {
  154. DIR* d = opendir(path.c_str());
  155. int r = -1;
  156. if (d)
  157. {
  158. struct dirent* p;
  159. r = 0;
  160. while (!r && (p = readdir(d)))
  161. {
  162. int r2 = 0;
  163. std::string fn = p->d_name;
  164. if (fn != "." && fn != "..")
  165. {
  166. fn = path + "/" + fn;
  167. struct stat statbuf;
  168. if (lstat(fn.c_str(), &statbuf) == 0)
  169. {
  170. if (S_ISLNK(statbuf.st_mode))
  171. r2 = unlink(fn.c_str());
  172. else if (S_ISDIR(statbuf.st_mode))
  173. r2 = removeDir(fn);
  174. else
  175. r2 = unlink(fn.c_str());
  176. }
  177. else
  178. {
  179. std::cout << "stat(" << fn << ") failed" << std::endl;
  180. // we assume "file" here
  181. r2 = unlink(fn.c_str());
  182. }
  183. }
  184. r = r2;
  185. }
  186. closedir(d);
  187. }
  188. if (r == 0)
  189. r = rmdir(path.c_str());
  190. return r;
  191. }
  192. #define POPEN_BUFFER_SIZE 2000
  193. Strings localExec(const std::string& cmd,
  194. int& rc, bool debug,
  195. const std::string& logfn)
  196. {
  197. if (debug)
  198. std::cout << "Executing " << cmd << std::endl;
  199. std::ofstream log;
  200. if (!logfn.empty())
  201. log.open(logfn);
  202. if (log.is_open())
  203. {
  204. log << "Executing " << cmd << std::endl;
  205. log << "--------------------------------------------------------" << std::endl;
  206. }
  207. Strings res;
  208. FILE* fd = popen(cmd.c_str(), "r");
  209. if (fd != nullptr)
  210. {
  211. char buffer[POPEN_BUFFER_SIZE];
  212. while (fgets(buffer, POPEN_BUFFER_SIZE - 1, fd))
  213. {
  214. buffer[POPEN_BUFFER_SIZE - 1] = 0; // force string end here
  215. int size = strlen(buffer);
  216. if (buffer[size - 1] == '\n') // substitute linefeed with string end
  217. buffer[size - 1] = 0;
  218. std::string input = buffer;
  219. if (log.is_open())
  220. log << input << std::endl;
  221. res.push_back(input);
  222. if (debug)
  223. std::cout << ">>" << input << "<<" << std::endl;
  224. }
  225. int st = pclose(fd);
  226. if (WIFEXITED(st))
  227. rc = WEXITSTATUS(st);
  228. else
  229. rc = 0;
  230. if (debug)
  231. std::cout << " result code: " << rc << std::endl;
  232. }
  233. else
  234. {
  235. if (debug)
  236. std::cout << " popen " << cmd << " failed " << std::endl;
  237. rc = 1;
  238. return res;
  239. }
  240. if (log.is_open())
  241. {
  242. log << "--------------------------------------------------------" << std::endl;
  243. log << "rsync exit value: " << rc << std::endl;
  244. }
  245. return res;
  246. }
  247. Strings remoteExec(const std::string& rshCommand,
  248. const std::string& cmd,
  249. int& rc, bool debug,
  250. const std::string& logfn)
  251. {
  252. return localExec(rshCommand + " " + cmd, rc, debug, logfn);
  253. }