MHWD::STATUS Mhwd::uninstallConfig(Config *config) { std::shared_ptr<Config> installedConfig{getInstalledConfig(config->name_, config->type_)}; // Check if installed if (nullptr == installedConfig) { return MHWD::STATUS::ERROR_NOT_INSTALLED; } else if (installedConfig->basePath_ != config->basePath_) { return MHWD::STATUS::ERROR_NO_MATCH_LOCAL_CONFIG; } else { // TODO: Should we check for local requirements here? // Run script if (!runScript(installedConfig, MHWD::TRANSACTIONTYPE::REMOVE)) { return MHWD::STATUS::ERROR_SCRIPT_FAILED; } if (!removeDirectory(installedConfig->basePath_)) { return MHWD::STATUS::ERROR_SET_DATABASE; } // Installed config vectors have to be updated manual with updateInstalledConfigData(Data*) return MHWD::STATUS::SUCCESS; } }
mhwd::STATUS mhwd::performTransaction(mhwd::Data *data, mhwd::Transaction *transaction) { if (transaction->type == mhwd::Transaction::TYPE_INSTALL && !transaction->conflictedConfigs.empty()) return STATUS_ERROR_CONFLICTS; else if (transaction->type == mhwd::Transaction::TYPE_REMOVE && !transaction->requiredByConfigs.empty()) return STATUS_ERROR_REQUIREMENTS; // Check if already installed mhwd::Config *installedConfig = getInstalledConfig(data, transaction->config->name, transaction->config->type); mhwd::STATUS status = STATUS_SUCCESS; if (transaction->type == mhwd::Transaction::TYPE_REMOVE || (installedConfig != NULL && transaction->allowReinstallation)) { if (installedConfig == NULL) return STATUS_ERROR_NOT_INSTALLED; emitMessageFunc(data, mhwd::MESSAGETYPE_REMOVE_START, installedConfig->name); if ((status = uninstallConfig(data, installedConfig)) != STATUS_SUCCESS) return status; emitMessageFunc(data, mhwd::MESSAGETYPE_REMOVE_END, installedConfig->name); } if (transaction->type == mhwd::Transaction::TYPE_INSTALL) { // Check if already installed but not allowed to reinstall if (installedConfig != NULL && !transaction->allowReinstallation) return STATUS_ERROR_ALREADY_INSTALLED; // Install all dependencies first for (std::vector<mhwd::Config*>::const_iterator it = transaction->dependencyConfigs.end() - 1; it != transaction->dependencyConfigs.begin() - 1; --it) { emitMessageFunc(data, mhwd::MESSAGETYPE_INSTALLDEPENDENCY_START, (*it)->name); if ((status = installConfig(data, (*it))) != STATUS_SUCCESS) return status; emitMessageFunc(data, mhwd::MESSAGETYPE_INSTALLDEPENDENCY_END, (*it)->name); } emitMessageFunc(data, mhwd::MESSAGETYPE_INSTALL_START, transaction->config->name); if ((status = installConfig(data, transaction->config)) != STATUS_SUCCESS) return status; emitMessageFunc(data, mhwd::MESSAGETYPE_INSTALL_END, transaction->config->name); } return status; }
int Mhwd::launch(int argc, char *argv[]) { std::vector<std::string> missingDirs { checkEnvironment() }; if (!missingDirs.empty()) { consoleWriter_.printError("Following directories do not exist:"); for (const auto& dir : missingDirs) { consoleWriter_.printStatus(dir); } return 1; } std::string operationType; bool autoConfigureNonFreeDriver = false; std::string autoConfigureClassID; try { tryToParseCmdLineOptions(argc, argv, autoConfigureNonFreeDriver, operationType, autoConfigureClassID); } catch(const std::runtime_error& e) { consoleWriter_.printError(e.what()); consoleWriter_.printHelp(); return 1; } if (!optionsDontInterfereWithEachOther()) { return 1; } // Check for invalid configs for (auto&& invalidConfig : data_.invalidConfigs) { consoleWriter_.printWarning("config '" + invalidConfig->configPath_ + "' is invalid!"); } // > Perform operations: // List all configs if (arguments_.LIST_ALL && arguments_.SHOW_PCI) { if (!data_.allPCIConfigs.empty()) { consoleWriter_.listConfigs(data_.allPCIConfigs, "All PCI configs:"); } else { consoleWriter_.printWarning("No PCI configs found!"); } } if (arguments_.LIST_ALL && arguments_.SHOW_USB) { if (!data_.allUSBConfigs.empty()) { consoleWriter_.listConfigs(data_.allUSBConfigs, "All USB configs:"); } else { consoleWriter_.printWarning("No USB configs found!"); } } // List installed configs if (arguments_.LIST_INSTALLED && arguments_.SHOW_PCI) { if (arguments_.DETAIL) { consoleWriter_.printInstalledConfigs("PCI", data_.installedPCIConfigs); } else { if (!data_.installedPCIConfigs.empty()) { consoleWriter_.listConfigs(data_.installedPCIConfigs, "Installed PCI configs:"); } else { consoleWriter_.printWarning("No installed PCI configs!"); } } } if (arguments_.LIST_INSTALLED && arguments_.SHOW_USB) { if (arguments_.DETAIL) { consoleWriter_.printInstalledConfigs("USB", data_.installedUSBConfigs); } else { if (!data_.installedUSBConfigs.empty()) { consoleWriter_.listConfigs(data_.installedUSBConfigs, "Installed USB configs:"); } else { consoleWriter_.printWarning("No installed USB configs!"); } } } // List available configs if (arguments_.LIST_AVAILABLE && arguments_.SHOW_PCI) { if (arguments_.DETAIL) { consoleWriter_.printAvailableConfigsInDetail("PCI", data_.PCIDevices); } else { for (auto&& PCIDevice : data_.PCIDevices) { if (!PCIDevice->availableConfigs_.empty()) { consoleWriter_.listConfigs(PCIDevice->availableConfigs_, PCIDevice->sysfsBusID_ + " (" + PCIDevice->classID_ + ":" + PCIDevice->vendorID_ + ":" + PCIDevice->deviceID_ + ") " + PCIDevice->className_ + " " + PCIDevice->vendorName_ + ":"); } } } } if (arguments_.LIST_AVAILABLE && arguments_.SHOW_USB) { if (arguments_.DETAIL) { consoleWriter_.printAvailableConfigsInDetail("USB", data_.USBDevices); } else { for (auto&& USBdevice : data_.USBDevices) { if (!USBdevice->availableConfigs_.empty()) { consoleWriter_.listConfigs(USBdevice->availableConfigs_, USBdevice->sysfsBusID_ + " (" + USBdevice->classID_ + ":" + USBdevice->vendorID_ + ":" + USBdevice->deviceID_ + ") " + USBdevice->className_ + " " + USBdevice->vendorName_ + ":"); } } } } // List hardware information if (arguments_.LIST_HARDWARE && arguments_.SHOW_PCI) { if (arguments_.DETAIL) { consoleWriter_.printDeviceDetails(hw_pci); } else { consoleWriter_.listDevices(data_.PCIDevices, "PCI"); } } if (arguments_.LIST_HARDWARE && arguments_.SHOW_USB) { if (arguments_.DETAIL) { consoleWriter_.printDeviceDetails(hw_usb); } else { consoleWriter_.listDevices(data_.USBDevices, "USB"); } } // Auto configuration if (arguments_.AUTOCONFIGURE) { std::vector<std::shared_ptr<Device>> *devices; std::vector<std::shared_ptr<Config>> *installedConfigs; if ("USB" == operationType) { devices = &data_.USBDevices; installedConfigs = &data_.installedUSBConfigs; } else { devices = &data_.PCIDevices; installedConfigs = &data_.installedPCIConfigs; } bool foundDevice = false; for (auto&& device : *devices) { if (device->classID_ != autoConfigureClassID) { continue; } else { foundDevice = true; std::shared_ptr<Config> config; for (auto&& availableConfig : device->availableConfigs_) { if (autoConfigureNonFreeDriver || availableConfig->freedriver_) { config = availableConfig; break; } } if (nullptr == config) { consoleWriter_.printWarning( "No config found for device: " + device->sysfsBusID_ + " (" + device->classID_ + ":" + device->vendorID_ + ":" + device->deviceID_ + ") " + device->className_ + " " + device->vendorName_ + " " + device->deviceName_); continue; } else { // If force is not set then skip found config bool skip = false; if (!arguments_.FORCE) { skip = std::find_if(installedConfigs->begin(), installedConfigs->end(), [&config](const std::shared_ptr<Config>& conf) -> bool { return conf->name_ == config->name_; }) != installedConfigs->end(); } // Print found config if (skip) { consoleWriter_.printStatus( "Skipping already installed config '" + config->name_ + "' for device: " + device->sysfsBusID_ + " (" + device->classID_ + ":" + device->vendorID_ + ":" + device->deviceID_ + ") " + device->className_ + " " + device->vendorName_ + " " + device->deviceName_); } else { consoleWriter_.printStatus( "Using config '" + config->name_ + "' for device: " + device->sysfsBusID_ + " (" + device->classID_ + ":" + device->vendorID_ + ":" + device->deviceID_ + ") " + device->className_ + " " + device->vendorName_ + " " + device->deviceName_); } bool alreadyInList = std::find(configs_.begin(), configs_.end(), config->name_) != configs_.end(); if (!alreadyInList && !skip) { configs_.push_back(config->name_); } } } } if (!foundDevice) { consoleWriter_.printWarning("No device of class " + autoConfigureClassID + " found!"); } else if (!configs_.empty()) { arguments_.INSTALL = true; } } // Transaction if (arguments_.INSTALL || arguments_.REMOVE) { if (!isUserRoot()) { consoleWriter_.printError("You cannot perform this operation unless you are root!"); } else { for (auto&& configName = configs_.begin(); configName != configs_.end(); configName++) { if (arguments_.CUSTOM_INSTALL) { // Custom install -> get configs struct stat filestatus; std::string filepath = (*configName) + "/MHWDCONFIG"; if (0 != stat(filepath.c_str(), &filestatus)) { consoleWriter_.printError("custom config '" + filepath + "' does not exist!"); return 1; } else if (!S_ISREG(filestatus.st_mode)) { consoleWriter_.printError("custom config '" + filepath + "' is invalid!"); return 1; } else { config_.reset(new Config(filepath, operationType)); if (!config_->readConfigFile(filepath)) { consoleWriter_.printError("failed to read custom config '" + filepath + "'!"); return 1; } else if (!performTransaction(config_, MHWD::TRANSACTIONTYPE::INSTALL)) { return 1; } } } else if (arguments_.INSTALL) { config_ = getAvailableConfig((*configName), operationType); if (config_ == nullptr) { config_ = getDatabaseConfig((*configName), operationType); if (config_ == nullptr) { consoleWriter_.printError("config '" + (*configName) + "' does not exist!"); return 1; } else { consoleWriter_.printWarning( "no matching device for config '" + (*configName) + "' found!"); } } if (!performTransaction(config_, MHWD::TRANSACTIONTYPE::INSTALL)) { return 1; } } else if (arguments_.REMOVE) { config_ = getInstalledConfig((*configName), operationType); if (nullptr == config_) { consoleWriter_.printError("config '" + (*configName) + "' is not installed!"); return 1; } else if (!performTransaction(config_, MHWD::TRANSACTIONTYPE::REMOVE)) { return 1; } } } } } return 0; }
MHWD::STATUS Mhwd::performTransaction(const Transaction& transaction) { if ((MHWD::TRANSACTIONTYPE::INSTALL == transaction.type_) && !transaction.conflictedConfigs_.empty()) { return MHWD::STATUS::ERROR_CONFLICTS; } else if ((MHWD::TRANSACTIONTYPE::REMOVE == transaction.type_) && !transaction.configsRequirements_.empty()) { return MHWD::STATUS::ERROR_REQUIREMENTS; } else { // Check if already installed std::shared_ptr<Config> installedConfig{getInstalledConfig(transaction.config_->name_, transaction.config_->type_)}; MHWD::STATUS status = MHWD::STATUS::SUCCESS; if ((MHWD::TRANSACTIONTYPE::REMOVE == transaction.type_) || (installedConfig != nullptr && transaction.isAllowedToReinstall())) { if (nullptr == installedConfig) { return MHWD::STATUS::ERROR_NOT_INSTALLED; } else { consoleWriter_.printMessage(MHWD::MESSAGETYPE::REMOVE_START, installedConfig->name_); if (MHWD::STATUS::SUCCESS != (status = uninstallConfig(installedConfig.get()))) { return status; } else { consoleWriter_.printMessage(MHWD::MESSAGETYPE::REMOVE_END, installedConfig->name_); } } } if (MHWD::TRANSACTIONTYPE::INSTALL == transaction.type_) { // Check if already installed but not allowed to reinstall if ((nullptr != installedConfig) && !transaction.isAllowedToReinstall()) { return MHWD::STATUS::ERROR_ALREADY_INSTALLED; } else { // Install all dependencies first for (auto&& dependencyConfig = transaction.dependencyConfigs_.end() - 1; dependencyConfig != transaction.dependencyConfigs_.begin() - 1; --dependencyConfig) { consoleWriter_.printMessage(MHWD::MESSAGETYPE::INSTALLDEPENDENCY_START, (*dependencyConfig)->name_); if (MHWD::STATUS::SUCCESS != (status = installConfig((*dependencyConfig)))) { return status; } else { consoleWriter_.printMessage(MHWD::MESSAGETYPE::INSTALLDEPENDENCY_END, (*dependencyConfig)->name_); } } consoleWriter_.printMessage(MHWD::MESSAGETYPE::INSTALL_START, transaction.config_->name_); if (MHWD::STATUS::SUCCESS != (status = installConfig(transaction.config_))) { return status; } else { consoleWriter_.printMessage(MHWD::MESSAGETYPE::INSTALL_END, transaction.config_->name_); } } } return status; } }