#include "unInstall.h" #include #include #include "File.h" bool installManager::logExists() { HANDLE fHandle; fHandle = CreateFile(this->logfileName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (fHandle == INVALID_HANDLE_VALUE) { return false; } CloseHandle(fHandle); return true; } bool installManager::ensureLog() { if (this->logExists() == false) { HANDLE fHandle; unInstallCommand command("InstallRoot"); // Get the parent directory of the log file, and store it as the root FilePath p(this->logfileName); FilePath *parent = p.parent(); command.addParameter(parent->pathString()); delete parent; if (this->modules["default"].begin()->command != "InstallRoot") { this->modules["default"].insert(this->modules["default"].begin(), command); } fHandle = CreateFile(this->logfileName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (fHandle != INVALID_HANDLE_VALUE) { CloseHandle(fHandle); return true; } return false; } else { if (this->modules["default"].begin()->command == "InstallRoot") { this->logfileName = this->modules["default"].begin()->parameters[0]; } } return true; } bool installManager::setLogFile(string filename) { this->logfileName = filename; this->setModule("default"); return true; } bool installManager::readLog() { string command; stringArray params; // don't try to open an non-existing log; this has serious // repercussions with bad old VC++ if (!this->logExists()) { this->setModule("default"); this->changed = false; return true; } // open the log file this->logfile.open(this->logfileName.c_str(), ios::in); #ifndef __BORLANDC__ if (this->logfile.is_open()) #else if (this->logfile.rdbuf()->is_open()) #endif { // Get the commands into this object from the existing log file while ((command = this->readCommand(params)) != "") { if (command[0] == '[' && command[command.length()-1] == ']') { this->setModule(command.substr(1, command.length() - 2)); } else { unInstallCommand action(command, params); this->storeCommand(action); } } // close the logfile this->logfile.close(); // and clear the status bits, 'cos VC++ doesn't clear them when // we reopen the file later. this->logfile.clear(); } this->changed = false; // set to the default module this->setModule("default"); return true; } void installManager::setModule(string moduleName) { this->currentModule = moduleName; } bool installManager::storeCommand(unInstallCommand &command) { this->modules[this->currentModule].push_back(command); this->changed = true; // set the "changed" flag return true; } bool installManager::writeCommand(unInstallCommand &command) { if (!this->writeString(command.command)) { return false; } for (unsigned int p = 0; p < command.parameters.size(); p ++) { if (!this->writeSeparator()) { return false; } if (!this->writeString(command.parameters[p])) { return false; } } if (!this->writeString("\n")) { return false; } return true; } bool installManager::writeString(char *buffer) { string s(buffer); return this->writeString(s); } bool installManager::writeString(string str) { bool quote; // TODO: check for space characters in str and quote if necessary quote = str.find_first_of(' ') < str.length(); if (quote) { this->logfile << "\""; } this->logfile << str; if (quote) { this->logfile << "\""; } return true; } bool installManager::writeSeparator() { this->logfile << " "; return true; } string installManager::readString() { string reply = ""; char c; if (this->logfile.eof()) { return reply; } this->logfile >> c; while (c <= ' ' && !this->logfile.eof()) { this->logfile.get(); } if (this->logfile.eof()) { return reply; } if (c == '\"') { do { c = this->logfile.get(); if (c != '\"') { reply += c; } } while (c != '\"' && !this->logfile.eof()); } else { while (c > ' ') { reply += c; if (this->logfile.eof()) { break; } c = this->logfile.get(); } if (!this->logfile.eof()) { this->logfile.putback(c); } //this->logfile >> reply; } return reply; } string installManager::readCommand(stringArray &array) { string reply = ""; char c; array.clear(); if (this->logfile.eof()) { return reply; } reply = this->readString(); if (reply == "") { return reply; } while(!this->logfile.eof() && (c = this->logfile.get()) != '\n') { this->logfile.putback(c); array.add(this->readString()); } if (!this->logfile.eof()) { this->logfile.putback(c); } return reply; } string installManager::popCommand(stringArray &array) { string command; if (this->modules[this->currentModule].size() == 0) { command = ""; } else { unsigned int last; last = this->modules[this->currentModule].size() - 1; command = this->modules[this->currentModule][last].commandName(); array = this->modules[this->currentModule][last].parameterList(); this->modules[this->currentModule].erase(this->modules[this->currentModule].begin() + last); } return command; } void installManager::abortLog(){ this->changed = false;} bool installManager::recordLog() { // just return if there are no changes to record if (this->changed == false) { return true; } // if the file didn't open, then this is almost certainly being compiled // with Microsoft Visual C++ which has a library which fails to open the // file if it doesn't already exist. Do a createfile and hope for success. // TODO: add proper error handling here this->ensureLog(); this->logfile.open(this->logfileName.c_str(), ios::out); #ifndef __BORLANDC__ if (!this->logfile.is_open()) #else if (!this->logfile.rdbuf()->is_open()) #endif { MessageBox(0, "Unable to open log file", this->logfileName.c_str(), MB_OK); } unInstallCommandMap::iterator here = this->modules.begin(); unInstallCommandMap::iterator end = this->modules.end(); while (here != end) { this->writeString("[" + (*here).first + "]\n"); unInstallCommandList::iterator ahere = (*here).second.begin(); unInstallCommandList::iterator aend = (*here).second.end(); while (ahere != aend) { this->writeCommand(*ahere); ahere ++; } here ++; } this->logfile.close(); this->changed = false; return true; } bool installManager::isEmpty() { unInstallCommandMap::iterator here = this->modules.begin(); unInstallCommandMap::iterator end = this->modules.end(); while (here != end) { this->writeString("[" + (*here).first + "]\n"); unInstallCommandList::iterator ahere = (*here).second.begin(); unInstallCommandList::iterator aend = (*here).second.end(); if (ahere != aend) { return false; } here ++; } return true; } string installManager::installRoot() { if (this->modules["default"].begin()->command != "InstallRoot") return ""; return this->modules["default"].begin()->parameters[0]; } installManager::~installManager() { this->recordLog(); }