// Utility.cpp // // Copyright (C) 2011, ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // This file implements the common functionality for the configuration // utilities. #include #include #include #include #include #include #include #include #include #include #include #include "Utility.hpp" using namespace std; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Configuration. //////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// const std::string Utility::DirectorySeparator("/"); /// SNF user name. const string SNFUserName = "snfuser"; /// SNF group name. const string SNFGroupName = "snfuser"; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // End of configuration. ///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// Utility::Utility() : DebugRequested(false), VerboseRequested(false), ExplainRequested(false), HelpRequested(false) { } bool Utility::FileExists(const std::string File) { bool Exists; std::ifstream Input; errno = 0; Input.open(File.c_str()); if (ENOENT == errno) { Exists = false; } else { Exists = true; } Input.close(); return Exists; } std::string Utility::ReadLastPartOfFile(std::string File, long Size) { if (!FileExists(File)) { return ""; } std::ifstream Input; Input.open(File.c_str()); if (!Input) { std::string Temp; Temp = "Error opening the file " + File; Temp += " to read from: "; Temp += strerror(errno); throw std::runtime_error(Temp); } std::streampos FileSize; FileSize = Input.tellg(); Input.seekg(0, ios_base::end); FileSize = Input.tellg() - FileSize; if (FileSize > Size) { Input.seekg(-Size, ios_base::end); } else { Input.seekg(0, ios_base::beg); } std::ostringstream Output; if (!Input.eof()) { // Copy if there are characters. // Copying an empty file causes Output << Input.rdbuf(); // failbit to be set. } if (Output.bad() || Output.fail()) { std::string Temp; Temp = "Error reading last part of file " + File; Temp += ". Content read: '"; Input.close(); Temp += Output.str(); Temp += "'"; throw std::runtime_error(Temp); } Input.close(); if (!Input) { std::string Temp; Temp = "Error closing the file " + File; Temp += " after reading: "; Temp += strerror(errno); throw std::runtime_error(Temp); } return Output.str(); } void Utility::Copy(std::string From, std::string To) { if (Verbose()) { cout << "Copy " << From << " to " << To << "..."; } if (!Explain()) { std::ifstream Input; Input.open(From.c_str()); if (!Input) { std::string Temp; Temp = "Error opening the file " + From; Temp += " to read from: "; Temp += strerror(errno); throw std::runtime_error(Temp); } std::ofstream Output; Output.open(To.c_str(), std::ios::trunc); if (!Output) { std::string Temp; Temp = "Error opening the file " + To; Temp += " to copy to: "; Temp += strerror(errno); throw std::runtime_error(Temp); } if (!Input.eof()) { // Copy if there are characters. // Copying an empty file causes Output << Input.rdbuf(); // failbit to be set. } if (Output.bad() || Output.fail()) { std::string Temp; Temp = "Error copying " + From; Temp += " to " + To; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Input.close(); if (!Input) { std::string Temp; Temp = "Error closing the file " + From; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output.close(); if (!Output) { std::string Temp; Temp = "Error closing the file " + To; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } } OutputVerboseEnd(); } void Utility::SetOwnerGroup(std::string File) { struct passwd *SNFPasswd; uid_t SNFUid; struct group *SNFGroup; gid_t SNFGid; if (Verbose()) { cout << "Set owner:group of " << File << " to " << SNFUserName << ":" << SNFGroupName << "..."; } if (!Explain()) { errno = 0; SNFPasswd = getpwnam(SNFUserName.c_str()); if (SNFPasswd == 0) { string Temp; Temp = "Error getting info for Sniffer user " + SNFUserName; Temp += ": "; Temp += ((errno == 0) ? "No such user; create the user and try again." : strerror(errno)); throw runtime_error(Temp); } SNFUid = SNFPasswd->pw_uid; SNFGid = SNFPasswd->pw_gid; if (chown(File.c_str(), SNFUid, SNFGid) != 0) { string Temp; Temp = "Error changing group and owner of file " + File; Temp += " to " + SNFUserName + ":" + SNFGroupName; Temp += ": "; Temp += strerror(errno); throw runtime_error(Temp); } } OutputVerboseEnd(); } void Utility::SetMode(std::string File, mode_t mode) { if (Verbose()) { cout << "Set mode of " << File << " to " << std::oct << mode << "..."; } if (!Explain()) { if (chmod(File.c_str(), mode) != 0) { ostringstream Temp; Temp << "Error changing permissions of file " << File << " to " << mode << ": " << strerror(errno); throw runtime_error(Temp.str()); } } OutputVerboseEnd(); } void Utility::MkDir(std::string &Dir) { if (Verbose()) { cout << "Create directory " << Dir << "..."; } if (!Explain()) { if (mkdir(Dir.c_str(), 0) != 0) { ostringstream Temp; Temp << "Error creating directory " << Dir << ": " << strerror(errno); throw runtime_error(Temp.str()); } } OutputVerboseEnd(); } void Utility::ReplaceXmlAttribute(std::string *Content, std::string ElementName, std::string AttributeName, std::string AttributeValue) { bool FoundElement; FoundElement = false; std::string::size_type ElementContentBegin; // Index of start of the element content. std::string::size_type ElementContentEnd; // One past the end of the element content. ElementContentBegin = 0; while (!FoundElement) { ElementContentBegin = Content->find("<" + ElementName, ElementContentBegin); // Get indices of element content. ElementContentEnd = Content->find("rfind("", ElementContentBegin); if ( (PrevCommentBegin == std::string::npos) || (PrevCommentEnd < ElementContentBegin) ) { FoundElement = true; break; // Not in comment; continue processing. } ElementContentBegin++; // In comment; continue search. } if (std::string::npos != Content->find("<" + ElementName, ElementContentBegin + 1)) { std::string Temp; Temp = "Found two elements named '" + ElementName; Temp += "'; there must be only one."; throw std::runtime_error(Temp); } if (std::string::npos == ElementContentEnd) { ElementContentEnd = Content->find("/>", ElementContentBegin); } if (std::string::npos == ElementContentEnd){ std::string Temp; Temp = "Unable to find the end of element '" + ElementName; Temp += "'."; throw std::runtime_error(Temp); } ElementContentBegin += ElementName.length() + 1; // Skip element name. std::string::size_type ProvisionalAttributeNameBegin = ElementContentBegin; std::string::size_type AttributeNameBegin ; bool FoundAttribute = false; std::string PrevChar; while (ProvisionalAttributeNameBegin < ElementContentEnd) { // Find start of attribute name. ProvisionalAttributeNameBegin = Content->find(AttributeName, ProvisionalAttributeNameBegin); if ( (ProvisionalAttributeNameBegin == std::string::npos) || (ProvisionalAttributeNameBegin >= ElementContentEnd) ) { break; } PrevChar = Content->at(ProvisionalAttributeNameBegin - 1); if (std::string::npos == PrevChar.find_first_not_of(" \t\r\n")) { // Check for whitespace before the attribute. if (FoundAttribute) { std::string Temp; Temp = "Found two attributes named '" + AttributeName; Temp += "' in element '" + ElementName; Temp += "'; there must be only one."; throw std::runtime_error(Temp); } FoundAttribute = true; AttributeNameBegin = ProvisionalAttributeNameBegin; } ProvisionalAttributeNameBegin = ProvisionalAttributeNameBegin + AttributeName.length(); // Skip. } if (!FoundAttribute) { std::string Temp; Temp = "Unable to find the attribute '" + AttributeName; Temp += "' in element '" + ElementName; Temp += "'."; throw std::runtime_error(Temp); } std::string::size_type EqualIndex; // Index of "=". std::string::size_type DelimiterIndex; // Index of delimiter of attribute value. std::string DelimiterValue; // Attribute value delimiter value. std::string::size_type AttributeValueBegin; // Index of start of attribute value. std::string::size_type AttributeValueEnd; // One past the end of the attribute value. EqualIndex = // Get index of first delimiter. Content->find_first_not_of(" \t\r\n", AttributeNameBegin + AttributeName.length()); if ( (EqualIndex == std::string::npos) || (EqualIndex >= ElementContentEnd) ) { std::string Temp; Temp = "Unable to find \"=\" after '" + AttributeName; Temp += "' in element '" + ElementName; Temp += "'."; throw std::runtime_error(Temp); } DelimiterIndex = // Get index of first delimiter. Content->find_first_not_of(" \t\r\n", EqualIndex + 1); if ( (DelimiterIndex == std::string::npos) || (DelimiterIndex >= ElementContentEnd) ) { std::string Temp; Temp = "Unable to find start of value of attribute '" + AttributeName; Temp += "' in element '" + ElementName; Temp += "'."; throw std::runtime_error(Temp); } DelimiterValue = Content->at(DelimiterIndex); AttributeValueBegin = DelimiterIndex + 1; AttributeValueEnd = Content->find(DelimiterValue, AttributeValueBegin); if ( (AttributeValueEnd == std::string::npos) || (AttributeValueEnd >= ElementContentEnd) ) { std::string Temp; Temp = "Unable to find the end of the value of '" + AttributeName; Temp += "' in element '" + ElementName; Temp += "'."; throw std::runtime_error(Temp); } Content->replace(AttributeValueBegin, AttributeValueEnd - AttributeValueBegin, ""); Content->insert(AttributeValueBegin, AttributeValue); } bool Utility::CheckForString(std::string Line, std::string SearchString) { string::size_type Indx; Indx = Line.find_first_not_of(" \t"); // Trim leading whitespace. if (string::npos != Indx) { Line = Line.substr(Indx); } if (Line.substr(0, SearchString.length()) == SearchString) { return true; } return false; } std::string Utility::Trim(std::string String) { std::string Whitespace(" \n\r\t"); std::string::size_type End = String.find_last_not_of(Whitespace); if (End == std::string::npos) { return std::string(); } std::string::size_type Start = String.find_first_not_of(Whitespace); if (Start == std::string::npos) { Start = 0; } return String.substr(Start, (End - Start) + 1); } void Utility::SetDebug(bool Mode) { DebugRequested = Mode; } bool Utility::Debug() { return DebugRequested; } void Utility::SetVerbose(bool Mode) { VerboseRequested = Mode; } bool Utility::Verbose() { return (VerboseRequested || ExplainRequested); } void Utility::SetExplain(bool Mode) { ExplainRequested = Mode; } bool Utility::Explain() { return ExplainRequested; } void Utility::SetHelp(bool Mode) { HelpRequested = Mode; } bool Utility::Help() { return HelpRequested; } void Utility::OutputVerboseEnd() { if (Verbose() && !Explain()) { cout << "done.\n"; } else if (Explain()) { cout << "\n"; } }