Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Utility.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. // Utility.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file implements the common functionality for the configuration
  7. // utilities.
  8. #include <cerrno>
  9. #include <cstring>
  10. #include <unistd.h>
  11. #include <pwd.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <stdexcept>
  15. #include <sstream>
  16. #include <iostream>
  17. #include <fstream>
  18. #include <vector>
  19. #include "Utility.hpp"
  20. using namespace std;
  21. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  23. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  24. const std::string Utility::DirectorySeparator("/");
  25. /// SNF user name.
  26. const string SNFUserName = "snfuser";
  27. /// SNF group name.
  28. const string SNFGroupName = "snfuser";
  29. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  30. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  31. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  32. Utility::Utility() {
  33. }
  34. bool
  35. Utility::FileExists(const std::string File) {
  36. if (Verbose()) {
  37. cout << "Check whether " << File << " exists...";
  38. }
  39. bool Exists;
  40. std::ifstream Input;
  41. errno = 0;
  42. Input.open(File.c_str());
  43. if (ENOENT == errno) {
  44. Exists = false;
  45. } else {
  46. Exists = true;
  47. }
  48. Input.close();
  49. OutputVerboseEnd();
  50. return Exists;
  51. }
  52. std::string
  53. Utility::ReadLastPartOfFile(std::string File, long Size) {
  54. if (!FileExists(File)) {
  55. return "";
  56. }
  57. std::ifstream Input;
  58. Input.open(File.c_str());
  59. if (!Input) {
  60. std::string Temp;
  61. Temp = "Error opening the file " + File;
  62. Temp += " to read from: ";
  63. Temp += strerror(errno);
  64. throw std::runtime_error(Temp);
  65. }
  66. Input.seekg(Size, ios_base::end);
  67. std::ostringstream Output;
  68. if (!Input.eof()) { // Copy if there are characters.
  69. // Copying an empty file causes
  70. Output << Input.rdbuf(); // failbit to be set.
  71. }
  72. if (Output.bad() || Output.fail()) {
  73. std::string Temp;
  74. Temp = "Error " + File;
  75. Temp += ": ";
  76. Temp += strerror(errno);
  77. throw std::runtime_error(Temp);
  78. }
  79. Input.close();
  80. if (!Input) {
  81. std::string Temp;
  82. Temp = "Error closing the file " + File;
  83. Temp += " after reading: ";
  84. Temp += strerror(errno);
  85. throw std::runtime_error(Temp);
  86. }
  87. return Output.str();
  88. }
  89. void
  90. Utility::Copy(std::string From, std::string To) {
  91. if (Verbose()) {
  92. cout << "Copy " << From << " to " << To << "...";
  93. }
  94. if (!Explain()) {
  95. std::ifstream Input;
  96. Input.open(From.c_str());
  97. if (!Input) {
  98. std::string Temp;
  99. Temp = "Error opening the file " + From;
  100. Temp += " to read from: ";
  101. Temp += strerror(errno);
  102. throw std::runtime_error(Temp);
  103. }
  104. std::ofstream Output;
  105. Output.open(To.c_str(), std::ios::trunc);
  106. if (!Output) {
  107. std::string Temp;
  108. Temp = "Error opening the file " + To;
  109. Temp += " to copy to: ";
  110. Temp += strerror(errno);
  111. throw std::runtime_error(Temp);
  112. }
  113. if (!Input.eof()) { // Copy if there are characters.
  114. // Copying an empty file causes
  115. Output << Input.rdbuf(); // failbit to be set.
  116. }
  117. if (Output.bad() || Output.fail()) {
  118. std::string Temp;
  119. Temp = "Error copying " + From;
  120. Temp += " to " + To;
  121. Temp += ": ";
  122. Temp += strerror(errno);
  123. throw std::runtime_error(Temp);
  124. }
  125. Input.close();
  126. if (!Input) {
  127. std::string Temp;
  128. Temp = "Error closing the file " + From;
  129. Temp += ": ";
  130. Temp += strerror(errno);
  131. throw std::runtime_error(Temp);
  132. }
  133. Output.close();
  134. if (!Output) {
  135. std::string Temp;
  136. Temp = "Error closing the file " + To;
  137. Temp += ": ";
  138. Temp += strerror(errno);
  139. throw std::runtime_error(Temp);
  140. }
  141. }
  142. OutputVerboseEnd();
  143. }
  144. void
  145. Utility::SetOwnerGroup(std::string File) {
  146. struct passwd *SNFPasswd;
  147. uid_t SNFUid;
  148. struct group *SNFGroup;
  149. gid_t SNFGid;
  150. if (Verbose()) {
  151. cout << "Set owner:group of " << File << " to "
  152. << SNFUserName << ":" << SNFGroupName << "...";
  153. }
  154. if (!Explain()) {
  155. SNFPasswd = getpwnam(SNFUserName.c_str());
  156. if (SNFPasswd == 0) {
  157. string Temp;
  158. Temp = "Error getting info for Sniffer user " + SNFUserName;
  159. Temp += ": ";
  160. Temp += strerror(errno);
  161. throw runtime_error(Temp);
  162. }
  163. SNFUid = SNFPasswd->pw_uid;
  164. SNFGid = SNFPasswd->pw_gid;
  165. if (chown(File.c_str(), SNFUid, SNFGid) != 0) {
  166. string Temp;
  167. Temp = "Error changing group and owner of file " + File;
  168. Temp += " to " + SNFUserName + ":" + SNFGroupName;
  169. Temp += ": ";
  170. Temp += strerror(errno);
  171. throw runtime_error(Temp);
  172. }
  173. }
  174. OutputVerboseEnd();
  175. }
  176. void
  177. Utility::SetMode(std::string File, mode_t mode) {
  178. if (Verbose()) {
  179. cout << "Set mode of " << File << " to "
  180. << std::oct << mode << "...";
  181. }
  182. if (!Explain()) {
  183. if (chmod(File.c_str(), mode) != 0) {
  184. ostringstream Temp;
  185. Temp << "Error changing permissions of file " << File
  186. << " to " << mode << ": " << strerror(errno);
  187. throw runtime_error(Temp.str());
  188. }
  189. }
  190. OutputVerboseEnd();
  191. }
  192. void
  193. Utility::MkDir(std::string &Dir) {
  194. if (Verbose()) {
  195. cout << "Create directory " << Dir << "...";
  196. }
  197. if (!Explain()) {
  198. if (mkdir(Dir.c_str(), 0) != 0) {
  199. ostringstream Temp;
  200. Temp << "Error creating directory " << Dir << ": " << strerror(errno);
  201. throw runtime_error(Temp.str());
  202. }
  203. }
  204. OutputVerboseEnd();
  205. }
  206. void
  207. Utility::ReplaceXmlAttribute(std::string *Content, std::string ElementName, std::string AttributeName, std::string AttributeValue) {
  208. std::string::size_type ElementContentBegin; // Index of start of the element content.
  209. std::string::size_type ElementContentEnd; // One past the end of the element content.
  210. ElementContentBegin = Content->find("<" + ElementName); // Get indices of element content.
  211. ElementContentEnd = Content->find("</" + ElementName);
  212. if (std::string::npos == ElementContentBegin) {
  213. std::string Temp;
  214. Temp = "Unable to find the start of element '" + ElementName;
  215. Temp += "'.";
  216. throw std::runtime_error(Temp);
  217. }
  218. if (std::string::npos != Content->find("<" + ElementName, ElementContentBegin + 1)) {
  219. std::string Temp;
  220. Temp = "Found two elements named '" + ElementName;
  221. Temp += "'; there must be only one.";
  222. throw std::runtime_error(Temp);
  223. }
  224. if (std::string::npos == ElementContentEnd) {
  225. ElementContentEnd = Content->find("/>", ElementContentBegin);
  226. }
  227. if (std::string::npos == ElementContentEnd){
  228. std::string Temp;
  229. Temp = "Unable to find the end of element '" + ElementName;
  230. Temp += "'.";
  231. throw std::runtime_error(Temp);
  232. }
  233. ElementContentBegin += ElementName.length() + 1; // Skip element name.
  234. std::string::size_type ProvisionalAttributeNameBegin = ElementContentBegin;
  235. std::string::size_type AttributeNameBegin ;
  236. bool FoundAttribute = false;
  237. std::string PrevChar;
  238. while (ProvisionalAttributeNameBegin < ElementContentEnd) { // Find start of attribute name.
  239. ProvisionalAttributeNameBegin = Content->find(AttributeName, ProvisionalAttributeNameBegin);
  240. if ( (ProvisionalAttributeNameBegin == std::string::npos) || (ProvisionalAttributeNameBegin >= ElementContentEnd) ) {
  241. break;
  242. }
  243. PrevChar = Content->at(ProvisionalAttributeNameBegin - 1);
  244. if (std::string::npos == PrevChar.find_first_not_of(" \t\r\n")) { // Check for whitespace before the attribute.
  245. if (FoundAttribute) {
  246. std::string Temp;
  247. Temp = "Found two attributes named '" + AttributeName;
  248. Temp += "' in element '" + ElementName;
  249. Temp += "'; there must be only one.";
  250. throw std::runtime_error(Temp);
  251. }
  252. FoundAttribute = true;
  253. AttributeNameBegin = ProvisionalAttributeNameBegin;
  254. }
  255. ProvisionalAttributeNameBegin = ProvisionalAttributeNameBegin + AttributeName.length(); // Skip.
  256. }
  257. if (!FoundAttribute) {
  258. std::string Temp;
  259. Temp = "Unable to find the attribute '" + AttributeName;
  260. Temp += "' in element '" + ElementName;
  261. Temp += "'.";
  262. throw std::runtime_error(Temp);
  263. }
  264. std::string::size_type EqualIndex; // Index of "=".
  265. std::string::size_type DelimiterIndex; // Index of delimiter of attribute value.
  266. std::string DelimiterValue; // Attribute value delimiter value.
  267. std::string::size_type AttributeValueBegin; // Index of start of attribute value.
  268. std::string::size_type AttributeValueEnd; // One past the end of the attribute value.
  269. EqualIndex = // Get index of first delimiter.
  270. Content->find_first_not_of(" \t\r\n", AttributeNameBegin + AttributeName.length());
  271. if ( (EqualIndex == std::string::npos) || (EqualIndex >= ElementContentEnd) ) {
  272. std::string Temp;
  273. Temp = "Unable to find \"=\" after '" + AttributeName;
  274. Temp += "' in element '" + ElementName;
  275. Temp += "'.";
  276. throw std::runtime_error(Temp);
  277. }
  278. DelimiterIndex = // Get index of first delimiter.
  279. Content->find_first_not_of(" \t\r\n", EqualIndex + 1);
  280. if ( (DelimiterIndex == std::string::npos) || (DelimiterIndex >= ElementContentEnd) ) {
  281. std::string Temp;
  282. Temp = "Unable to find start of value of attribute '" + AttributeName;
  283. Temp += "' in element '" + ElementName;
  284. Temp += "'.";
  285. throw std::runtime_error(Temp);
  286. }
  287. DelimiterValue = Content->at(DelimiterIndex);
  288. AttributeValueBegin = DelimiterIndex + 1;
  289. AttributeValueEnd = Content->find(DelimiterValue, AttributeValueBegin);
  290. if ( (AttributeValueEnd == std::string::npos) || (AttributeValueEnd >= ElementContentEnd) ) {
  291. std::string Temp;
  292. Temp = "Unable to find the end of the value of '" + AttributeName;
  293. Temp += "' in element '" + ElementName;
  294. Temp += "'.";
  295. throw std::runtime_error(Temp);
  296. }
  297. Content->replace(AttributeValueBegin,
  298. AttributeValueEnd - AttributeValueBegin,
  299. "");
  300. Content->insert(AttributeValueBegin, AttributeValue);
  301. }
  302. bool
  303. Utility::CheckForString(std::string Line, std::string SearchString) {
  304. string::size_type Indx;
  305. Indx = Line.find_first_not_of(" \t"); // Trim leading whitespace.
  306. if (string::npos != Indx) {
  307. Line = Line.substr(Indx);
  308. }
  309. if (Line.substr(0, SearchString.length()) == SearchString) {
  310. return true;
  311. }
  312. return false;
  313. }
  314. std::string
  315. Utility::Trim(std::string String) {
  316. std::string Whitespace(" \n\r\t");
  317. std::string::size_type End = String.find_last_not_of(Whitespace);
  318. if (End == std::string::npos) {
  319. return std::string();
  320. }
  321. std::string::size_type Start = String.find_first_not_of(Whitespace);
  322. if (Start == std::string::npos) {
  323. Start = 0;
  324. }
  325. return String.substr(Start, (End - Start) + 1);
  326. }
  327. void
  328. Utility::SetDebug(bool Mode) {
  329. DebugRequested = Mode;
  330. }
  331. bool
  332. Utility::Debug() {
  333. return DebugRequested;
  334. }
  335. void
  336. Utility::SetVerbose(bool Mode) {
  337. VerboseRequested = Mode;
  338. }
  339. bool
  340. Utility::Verbose() {
  341. return (VerboseRequested || ExplainRequested);
  342. }
  343. void
  344. Utility::SetExplain(bool Mode) {
  345. ExplainRequested = Mode;
  346. }
  347. bool
  348. Utility::Explain() {
  349. return ExplainRequested;
  350. }
  351. void
  352. Utility::SetHelp(bool Mode) {
  353. HelpRequested = Mode;
  354. }
  355. bool
  356. Utility::Help() {
  357. return HelpRequested;
  358. }
  359. void
  360. Utility::OutputVerboseEnd() {
  361. if (Verbose() && !Explain()) {
  362. cout << "done.\n";
  363. } else if (Explain()) {
  364. cout << "\n";
  365. }
  366. }