/******************************************************************************* * Copyright (C) 2013-2015 Ragnar Thomsen * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 2 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along * * with this program. If not, see . * *******************************************************************************/ #include "confoption.h" #include "fsutil.h" #include // Initialize two static class members QStringList confOption::capabilities = QStringList() << "CAP_AUDIT_CONTROL" << "CAP_AUDIT_WRITE" << "CAP_BLOCK_SUSPEND" << "CAP_CHOWN" << "CAP_DAC_OVERRIDE" << "CAP_DAC_READ_SEARCH" << "CAP_FOWNER" << "CAP_FSETID" << "CAP_IPC_LOCK" << "CAP_IPC_OWNER" << "CAP_KILL" << "CAP_LEASE" << "CAP_LINUX_IMMUTABLE" << "CAP_MAC_ADMIN" << "CAP_MAC_OVERRIDE" << "CAP_MKNOD" << "CAP_NET_ADMIN" << "CAP_NET_BIND_SERVICE" << "CAP_NET_BROADCAST" << "CAP_NET_RAW" << "CAP_SETGID" << "CAP_SETFCAP" << "CAP_SETPCAP" << "CAP_SETUID" << "CAP_SYS_ADMIN" << "CAP_SYS_BOOT" << "CAP_SYS_CHROOT" << "CAP_SYS_MODULE" << "CAP_SYS_NICE" << "CAP_SYS_PACCT" << "CAP_SYS_PTRACE" << "CAP_SYS_RAWIO" << "CAP_SYS_RESOURCE" << "CAP_SYS_TIME" << "CAP_SYS_TTY_CONFIG" << "CAP_SYSLOG" << "CAP_WAKE_ALARM"; bool confOption::operator==(const confOption& other) const { // Required for indexOf() if (uniqueName == other.uniqueName) return true; else return false; } confOption::confOption() { } confOption::confOption(QString newName) { // Create an instance necessary for indexOf() or == uniqueName = newName; } confOption::confOption(QVariantMap map) { file = static_cast(map["file"].toInt()); realName = map["name"].toString(); uniqueName = QString(map["name"].toString() + '_' + QString::number(file)); type = static_cast(map["type"].toInt()); defVal = map["defVal"]; possibleVals = map["possibleVals"].toStringList(); if (map.contains("defUnit")) defUnit = static_cast(map["defUnit"].toInt()); if (map.contains("defReadUnit")) defReadUnit = static_cast(map["defReadUnit"].toInt()); // These two are not used for anything currently // minUnit = static_cast(map["minUnit"].toInt()); // maxUnit = static_cast(map["maxUnit"].toInt()); if (map.contains("minVal")) minVal = map["minVal"].toLongLong(); if (map.contains("maxVal")) maxVal = map["maxVal"].toLongLong(); toolTip = map["toolTip"].toString(); hasNsec = map["hasNsec"].toBool(); if (type == MULTILIST) { // Create a map where all possibleVals are set to false. QVariantMap defMap; foreach (const QString &s, possibleVals) { defMap[s] = false; } defVal = defMap; } if (type == RESLIMIT) defVal = -1; value = defVal; } int confOption::setValue(QVariant newVal) { qDebug() << "Setting " << realName << " to " << newVal; value = newVal; return 0; } int confOption::setValueFromFile(QString line) { // Used to set values in confOptions from a file line QString rval = line.section('=',1).trimmed(); qDebug() << "setting " << realName << " to " << rval << " (from file)"; if (type == BOOL) { if (rval == "true" || rval == "on" || rval == "yes") { value = true; return 0; } else if (rval == "false" || rval == "off" || rval == "no") { value = false; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == INTEGER) { bool ok; qlonglong rvalToNmbr = rval.toLongLong(&ok); if (ok && rvalToNmbr >= minVal && rvalToNmbr <= maxVal) { value = rvalToNmbr; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == STRING) { value = rval; return 0; } else if (type == LIST) { if (realName == "ShowStatus") // ShowStatus needs special treatment { if (rval.toLower() == "true" || rval.toLower() == "on") rval = "yes"; else if (rval.toLower() == "false" || rval.toLower() == "off") rval = "no"; } if (possibleVals.contains(rval)) { value = rval.toLower(); return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; value = defVal; return -1; } else if (type == MULTILIST) { QVariantMap map; QStringList readList = rval.split(' ', QString::SkipEmptyParts); for (int i = 0; i < readList.size(); ++i) { if (!possibleVals.contains(readList.at(i))) { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } for (int i = 0; i < possibleVals.size(); ++i) { if (readList.contains(possibleVals.at(i))) map[possibleVals.at(i)] = true; else map[possibleVals.at(i)] = false; } value = map; return 0; } else if (type == TIME) { int pos = 0; QRegExp rxValid; // These regex check whether rval is a valid time interval if (hasNsec) rxValid = QRegExp("^(?:\\d*\\.?\\d *(ns|nsec|us|usec|ms|msec|s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours|d|day|days|w|week|weeks|month|months|y|year|years)? *)+$"); else rxValid = QRegExp("^(?:\\d*\\.?\\d *(us|usec|ms|msec|s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours|d|day|days|w|week|weeks|month|months|y|year|years)? *)+$"); pos = rxValid.indexIn(rval); if (pos > -1) { pos = 0; seconds secs(0); // This regex parses individual elements of the time interval QRegExp rxTimeParse = QRegExp("(\\d*\\.?\\d+) *([a-z]*)"); while ((pos = rxTimeParse.indexIn(rval, pos)) != -1) { if (rxTimeParse.cap(2) == "ns" || rxTimeParse.cap(2) == "nsec" ) { nanoseconds ns(rxTimeParse.cap(1).trimmed().toDouble()); secs += ns; } else if (rxTimeParse.cap(2) == "us" || rxTimeParse.cap(2) == "usec" ) { microseconds us(rxTimeParse.cap(1).trimmed().toDouble()); secs += us; } else if (rxTimeParse.cap(2) == "ms" || rxTimeParse.cap(2) == "msec" ) { milliseconds ms(rxTimeParse.cap(1).trimmed().toDouble()); secs += ms; } else if (rxTimeParse.cap(2) == "s" || rxTimeParse.cap(2) == "sec" || rxTimeParse.cap(2) == "second" || rxTimeParse.cap(2) == "seconds" ) { seconds s(rxTimeParse.cap(1).trimmed().toDouble()); secs += s; } else if (rxTimeParse.cap(2) == "m" || rxTimeParse.cap(2) == "min" || rxTimeParse.cap(2) == "minute" || rxTimeParse.cap(2) == "minutes" ) { minutes min(rxTimeParse.cap(1).trimmed().toDouble()); secs += min; } else if (rxTimeParse.cap(2) == "h" || rxTimeParse.cap(2) == "hr" || rxTimeParse.cap(2) == "hour" || rxTimeParse.cap(2) == "hours" ) { hours hr(rxTimeParse.cap(1).trimmed().toDouble()); secs += hr; } else if (rxTimeParse.cap(2) == "d" || rxTimeParse.cap(2) == "day" || rxTimeParse.cap(2) == "days") { days dy(rxTimeParse.cap(1).trimmed().toDouble()); secs += dy; } else if (rxTimeParse.cap(2) == "w" || rxTimeParse.cap(2) == "week" || rxTimeParse.cap(2) == "weeks") { weeks w(rxTimeParse.cap(1).trimmed().toDouble()); secs += w; } else if (rxTimeParse.cap(2) == "month" || rxTimeParse.cap(2) == "months") { months m(rxTimeParse.cap(1).trimmed().toDouble()); secs += m; } else if (rxTimeParse.cap(2) == "y" || rxTimeParse.cap(2) == "year" || rxTimeParse.cap(2) == "years") { years y(rxTimeParse.cap(1).trimmed().toDouble()); secs += y; } else if (rxTimeParse.cap(2).isEmpty()) { // unitless number, convert it from defReadUnit to seconds seconds tmpSeconds(convertTimeUnit(rxTimeParse.cap(1).trimmed().toDouble(), defReadUnit, timeUnit::s).toDouble()); secs += tmpSeconds; } pos += rxTimeParse.matchedLength(); } // Convert the read value in seconds to defUnit if (defUnit == ns) value = nanoseconds(secs).count(); else if (defUnit == us) value = microseconds(secs).count(); else if (defUnit == ms) value = milliseconds(secs).count(); else if (defUnit == s) value = secs.count(); else if (defUnit == min) value = minutes(secs).count(); else if (defUnit == h) value = hours(secs).count(); else if (defUnit == d) value = days(secs).count(); else if (defUnit == w) value = weeks(secs).count(); else if (defUnit == month) value = months(secs).count(); else if (defUnit == year) value = years(secs).count(); value = value.toULongLong(); // Convert to ulonglong (we don't support float in ui) return 0; } else { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } else if (type == RESLIMIT) { bool ok; int nmbr = rval.toUInt(&ok); if (ok) { value = nmbr; return 0; } else if (rval.toLower().trimmed() == "infinity" || rval.trimmed().isEmpty()) { value = -1; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == SIZE) { // RegExp to match a number (possibly with decimals) followed by a // size unit (or no unit for byte), or a % (for RuntimeDirectorySize) QRegExp rxSize; if (realName == "RuntimeDirectorySize") rxSize = QRegExp("^(\\d+\\.?\\d*)(K|M|G|T|P|E|%)?$"); else rxSize = QRegExp("^(\\d+\\.?\\d*)(K|M|G|T|P|E)?$"); int pos = 0; pos = rxSize.indexIn(rval); if (pos > -1 && rxSize.cap(0) == rval.trimmed()) { // convert the specified size unit to megabytes if (rxSize.cap(2) == "K") value = rxSize.cap(1).toDouble() / 1024; else if (rxSize.cap(2) == "M") value = rxSize.cap(1).toDouble(); else if (rxSize.cap(2) == "G") value = rxSize.cap(1).toDouble() * 1024; else if (rxSize.cap(2) == "T") value = rxSize.cap(1).toDouble() * 1024 * 1024; else if (rxSize.cap(2) == "P") value = rxSize.cap(1).toDouble() * 1024 * 1024 * 1024; else if (rxSize.cap(2) == "E") value = rxSize.cap(1).toDouble() * 1024 * 1024 * 1024 * 1024; else value = rxSize.cap(1).toDouble() / 1024 / 1024; if (realName == "RuntimeDirectorySize") { // This option supports both size units and % if (rxSize.cap(2) == "%") { value = rxSize.cap(1).toInt(); } else { bool ok = false; qulonglong sizeMB = getPartitionSize("/run", &ok) / 1024 / 1024; if (!ok) { qDebug() << rval << "cannot be interpreted correctly with an unknown partition size. Ignoring..."; return -1; } // Convert the size to percentage of physical RAM. The volatile // partition size should be half the physical RAM. value = 50 * value.toDouble() / sizeMB; } } // Convert from double to ulonglong (we don't support float in ui) value = value.toULongLong(); return 0; } else { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } return -1; } bool confOption::isDefault() const { if (value == defVal) return true; else return false; } void confOption::setToDefault() { value = defVal; } QVariant confOption::getValue() const { return value; } QString confOption::getValueAsString() const { // Used when fetching data for the QTableView if (type == MULTILIST) { QVariantMap map = value.toMap(); QString mapAsString; for(QVariantMap::const_iterator iter = map.constBegin(); iter != map.constEnd(); ++iter) { if (iter.value() == true && mapAsString.isEmpty()) mapAsString = QString(iter.key()); else if (iter.value() == true) mapAsString = QString(mapAsString + ' ' + iter.key()); } return mapAsString; } return value.toString(); } QString confOption::getLineForFile() const { // Used for saving to conf files if (value == defVal) { // value is set to default return QString('#' + realName + "=\n"); } else { // value is not default if (type == BOOL) { if (value.toBool()) return QString(realName + '=' + "yes\n"); else return QString(realName + '=' + "no\n"); } else if (type == MULTILIST) { if (!value.toMap().isEmpty()) { QVariantMap map = value.toMap(); QString ret; for(QVariantMap::const_iterator iter = map.constBegin(); iter != map.constEnd(); ++iter) { if (iter.value().toBool()) ret = QString(ret + iter.key() + ' '); } return QString(realName + '=' + ret.trimmed() + '\n'); } } else if (type == TIME) { if (value.toULongLong() == 0) return QString(realName + '=' + value.toString() + '\n'); else { if (defUnit == ns) return QString(realName + '=' + value.toString() + "ns\n"); else if (defUnit == us) return QString(realName + '=' + value.toString() + "us\n"); else if (defUnit == ms) return QString(realName + '=' + value.toString() + "ms\n"); else if (defUnit == s) return QString(realName + '=' + value.toString() + "s\n"); else if (defUnit == min) return QString(realName + '=' + value.toString() + "min\n"); else if (defUnit == h) return QString(realName + '=' + value.toString() + "h\n"); else if (defUnit == d) return QString(realName + '=' + value.toString() + "d\n"); else if (defUnit == w) return QString(realName + '=' + value.toString() + "w\n"); else if (defUnit == month) return QString(realName + '=' + value.toString() + "month\n"); else if (defUnit == year) return QString(realName + '=' + value.toString() + "year\n"); } } else if (type == SIZE) { return QString(realName + '=' + value.toString() + "M\n"); } return QString(realName + '=' + value.toString() + '\n'); } // not default } QString confOption::getFilename() const { if (file == SYSTEMD) return QString("system.conf"); else if (file == JOURNALD) return QString("journald.conf"); else if (file == LOGIND) return QString("logind.conf"); else if (file == COREDUMP) return QString("coredump.conf"); return QString(""); } QString confOption::getTimeUnit() const { QStringList timeUnitAsString = QStringList() << "ns" << "us" << "ms" << "s" << "min" << "h" << "days" << "weeks" << "month" << "year"; return timeUnitAsString.at(defUnit); } QVariant confOption::convertTimeUnit(double value, timeUnit oldTime, timeUnit newTime) { QVariant convertedVal; seconds tmpSecs(0); if (oldTime == ns) { nanoseconds val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == us) { microseconds val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == ms) { milliseconds val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == s) { seconds val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == min) { minutes val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == h) { hours val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == d) { days val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == w) { weeks val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == month) { months val(value); tmpSecs = chrono::duration_cast(val); } else if (oldTime == year) { years val(value); tmpSecs = chrono::duration_cast(val); } if (newTime == ns) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == us) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == ms) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == s) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == min) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == h) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == d) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == w) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == month) convertedVal = chrono::duration_cast(tmpSecs).count(); else if (newTime == year) convertedVal = chrono::duration_cast(tmpSecs).count(); return convertedVal; }