From 454845e14e1c34762cffa3021be7a552b1c64c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 16 Sep 2017 20:41:45 +0100 Subject: [PATCH] Port from MountEntry to FstabEntry. This helps to preserve comments in fstab file BUG: 305469 --- src/gui/editmountoptionsdialog.cpp | 4 +- src/gui/editmountpointdialog.cpp | 6 +- src/gui/editmountpointdialogwidget.cpp | 235 +++++++------------------ src/gui/editmountpointdialogwidget.h | 17 +- 4 files changed, 77 insertions(+), 185 deletions(-) diff --git a/src/gui/editmountoptionsdialog.cpp b/src/gui/editmountoptionsdialog.cpp index 166acd8..eecc137 100644 --- a/src/gui/editmountoptionsdialog.cpp +++ b/src/gui/editmountoptionsdialog.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2009, 2010 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2017 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -56,7 +56,7 @@ EditMountOptionsDialog::~EditMountOptionsDialog() QStringList EditMountOptionsDialog::options() { QStringList rval; - const QStringList lines = widget().editOptions().toPlainText().split(QStringLiteral("\n")); + const QStringList lines = widget().editOptions().toPlainText().split(QLatin1Char('\n')); for (const auto &line : lines) rval.append(line.simplified().toLower()); return rval; diff --git a/src/gui/editmountpointdialog.cpp b/src/gui/editmountpointdialog.cpp index b93f2a8..d6fe3f7 100644 --- a/src/gui/editmountpointdialog.cpp +++ b/src/gui/editmountpointdialog.cpp @@ -72,8 +72,12 @@ void EditMountPointDialog::accept() QStringLiteral("reallyWriteMountPoints")) == KMessageBox::Cancel) return; - if (widget().acceptChanges() && widget().writeMountpoints(QStringLiteral("/etc/fstab"))) + if (writeMountpoints(widget().fstabEntries())) partition().setMountPoint(widget().editPath().text()); + else + KMessageBox::sorry(this, + xi18nc("@info", "Could not save mount points to file /etc/fstab."), + xi18nc("@title:window", "Error While Saving Mount Points")); QDialog::accept(); } diff --git a/src/gui/editmountpointdialogwidget.cpp b/src/gui/editmountpointdialogwidget.cpp index f662576..856be6c 100644 --- a/src/gui/editmountpointdialogwidget.cpp +++ b/src/gui/editmountpointdialogwidget.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2009, 2010 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016, 2017 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -20,7 +20,6 @@ #include "gui/editmountoptionsdialog.h" #include -#include #include #include @@ -35,31 +34,13 @@ #include #include -#include #include -static QString findBlkIdDevice(const QString& token, const QString& value) -{ - blkid_cache cache; - QString rval; - - if (blkid_get_cache(&cache, nullptr) == 0) { - if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), &cache)) { - rval = QString::fromLocal8Bit(c); - free(c); - } - - blkid_put_cache(cache); - } - - return rval; -} - EditMountPointDialogWidget::EditMountPointDialogWidget(QWidget* parent, const Partition& p) : QWidget(parent), m_Partition(p) { - readMountpoints(QStringLiteral("/etc/fstab")); + m_fstabEntries = readFstabEntries(); setupUi(this); @@ -71,45 +52,60 @@ EditMountPointDialogWidget::EditMountPointDialogWidget(QWidget* parent, const Pa labelName().setText(m_deviceNode); labelType().setText(partition().fileSystem().name()); - if (mountPoints().find(m_deviceNode) == mountPoints().end()) - mountPoints().insert(std::pair(m_deviceNode, new MountEntry(m_deviceNode, QString(), partition().fileSystem().name(), QStringList(), 0, 0, MountEntry::deviceNode))); - - auto search = mountPoints().find(m_deviceNode); // FIXME: Only one mountpoint entry corresponding to given device is shown - MountEntry* entry = search->second; - - Q_ASSERT(entry); - - if (entry) { - editPath().setText(entry->path); - - spinDumpFreq().setValue(entry->dumpFreq); - spinPassNumber().setValue(entry->passNumber); - - switch (entry->identifyType) { - case MountEntry::uuid: - radioUUID().setChecked(true); - break; - - case MountEntry::label: - radioLabel().setChecked(true); - break; - - default: - radioDeviceNode().setChecked(true); + bool entryFound = false; + for (auto &e : m_fstabEntries) { + if (e.deviceNode() == m_deviceNode) { // FIXME kernel paths, fix multiple mountpoints + entryFound = true; + entry = &e; } - - boxOptions()[QStringLiteral("ro")] = m_CheckReadOnly; - boxOptions()[QStringLiteral("users")] = m_CheckUsers; - boxOptions()[QStringLiteral("noauto")] = m_CheckNoAuto; - boxOptions()[QStringLiteral("noatime")] = m_CheckNoAtime; - boxOptions()[QStringLiteral("nodiratime")] = m_CheckNoDirAtime; - boxOptions()[QStringLiteral("sync")] = m_CheckSync; - boxOptions()[QStringLiteral("noexec")] = m_CheckNoExec; - boxOptions()[QStringLiteral("relatime")] = m_CheckRelAtime; - - setupOptions(entry->options); } + // FIXME name() != fstabfsname (swap) + if (!entryFound) { + entry = new FstabEntry(m_deviceNode, QString(), partition().fileSystem().name(), QString()); + m_fstabEntries.append(*entry); + } + + editPath().setText(entry->mountPoint()); + + spinDumpFreq().setValue(entry->dumpFreq()); + spinPassNumber().setValue(entry->passNumber()); + + switch (entry->entryType()) { + case FstabEntryType::uuid: + radioUUID().setChecked(true); + break; + + case FstabEntryType::label: + radioLabel().setChecked(true); + break; + + case FstabEntryType::partuuid: + radioUUID().setChecked(true); + break; + + case FstabEntryType::partlabel: + radioLabel().setChecked(true); + break; + + case FstabEntryType::deviceNode: + radioDeviceNode().setChecked(true); + break; + case FstabEntryType::comment: + break; + } + + boxOptions()[QStringLiteral("ro")] = m_CheckReadOnly; + boxOptions()[QStringLiteral("users")] = m_CheckUsers; + boxOptions()[QStringLiteral("noauto")] = m_CheckNoAuto; + boxOptions()[QStringLiteral("noatime")] = m_CheckNoAtime; + boxOptions()[QStringLiteral("nodiratime")] = m_CheckNoDirAtime; + boxOptions()[QStringLiteral("sync")] = m_CheckSync; + boxOptions()[QStringLiteral("noexec")] = m_CheckNoExec; + boxOptions()[QStringLiteral("relatime")] = m_CheckRelAtime; + + setupOptions(entry->options()); + if (partition().fileSystem().uuid().isEmpty()) { radioUUID().setEnabled(false); if (radioUUID().isChecked()) @@ -128,8 +124,6 @@ EditMountPointDialogWidget::EditMountPointDialogWidget(QWidget* parent, const Pa EditMountPointDialogWidget::~EditMountPointDialogWidget() { - for (const auto &mp : mountPoints()) - delete mp.second; } void EditMountPointDialogWidget::setupOptions(const QStringList& options) @@ -175,124 +169,17 @@ QStringList EditMountPointDialogWidget::options() const return optList; } -bool EditMountPointDialogWidget::readMountpoints(const QString& filename) +void EditMountPointDialogWidget::acceptChanges() { - FILE* fp = setmntent(filename.toLocal8Bit().constData(), "r"); - - if (fp == nullptr) { - KMessageBox::sorry(this, - xi18nc("@info", "Could not open mount point file %1.", filename), - xi18nc("@title:window", "Error while reading mount points")); - return false; - } - - struct mntent* mnt = nullptr; - - while ((mnt = getmntent(fp)) != nullptr) { - QString device = QString::fromUtf8(mnt->mnt_fsname); - MountEntry::IdentifyType type = MountEntry::deviceNode; - - if (device.startsWith(QStringLiteral("UUID="))) { - type = MountEntry::uuid; - device = findBlkIdDevice(QStringLiteral("UUID"), QString(device).remove(QStringLiteral("UUID="))); - } else if (device.startsWith(QStringLiteral("LABEL="))) { - type = MountEntry::label; - device = findBlkIdDevice(QStringLiteral("LABEL"), QString(device).remove(QStringLiteral("LABEL="))); - } else if (device.startsWith(QStringLiteral("/"))) - device = QFile::symLinkTarget(device); - - if (!device.isEmpty()) { - QString mountPoint = QString::fromUtf8(mnt->mnt_dir); - mountPoints().insert(std::pair(device, new MountEntry(mnt, type))); - } - } - - endmntent(fp); - - return true; -} - -static void writeEntry(QFile& output, const MountEntry* entry) -{ - Q_ASSERT(entry); - - if (entry == nullptr) - return; - - if (entry->path.isEmpty()) - return; - - QTextStream s(&output); - - s << entry->name << "\t" - << entry->path << "\t" - << entry->type << "\t" - << (entry->options.size() > 0 ? entry->options.join(QStringLiteral(",")) : QStringLiteral("defaults")) << "\t" - << entry->dumpFreq << "\t" - << entry->passNumber << "\n"; -} - -bool EditMountPointDialogWidget::acceptChanges() -{ - MountEntry* entry = nullptr; - - if (mountPoints().find(labelName().text()) == mountPoints().end()) { - qWarning() << "could not find device " << labelName().text() << " in mount points."; - return false; - } - - auto search = mountPoints().find(labelName().text()); - entry = search->second; - - entry->dumpFreq = spinDumpFreq().value(); - entry->passNumber = spinPassNumber().value(); - entry->path = editPath().text(); - entry->options = options(); + entry->setDumpFreq(spinDumpFreq().value()); + entry->setPassNumber(spinPassNumber().value()); + entry->setMountPoint(editPath().text()); + entry->setOptions(options()); if (radioUUID().isChecked() && !partition().fileSystem().uuid().isEmpty()) - entry->name = QStringLiteral("UUID=") + partition().fileSystem().uuid(); + entry->setFsSpec(QStringLiteral("UUID=") + partition().fileSystem().uuid()); else if (radioLabel().isChecked() && !partition().fileSystem().label().isEmpty()) - entry->name = QStringLiteral("LABEL=") + partition().fileSystem().label(); + entry->setFsSpec(QStringLiteral("LABEL=") + partition().fileSystem().label()); else - entry->name = m_deviceNode; - - return true; -} - -bool EditMountPointDialogWidget::writeMountpoints(const QString& filename) -{ - bool rval = true; - const QString newFilename = QStringLiteral("%1.new").arg(filename); - QFile out(newFilename); - - if (!out.open(QFile::ReadWrite | QFile::Truncate)) { - qWarning() << "could not open output file " << newFilename; - rval = false; - } else { - const auto mp = mountPoints(); - for (const auto &me : mp) - writeEntry(out, me.second); - - out.close(); - - const QString bakFilename = QStringLiteral("%1.bak").arg(filename); - QFile::remove(bakFilename); - - if (QFile::exists(filename) && !QFile::rename(filename, bakFilename)) { - qWarning() << "could not rename " << filename << " to " << bakFilename; - rval = false; - } - - if (rval && !QFile::rename(newFilename, filename)) { - qWarning() << "could not rename " << newFilename << " to " << filename; - rval = false; - } - } - - if (!rval) - KMessageBox::sorry(this, - xi18nc("@info", "Could not save mount points to file %1.", filename), - xi18nc("@title:window", "Error While Saving Mount Points")); - - return rval; + entry->setFsSpec(m_deviceNode); } diff --git a/src/gui/editmountpointdialogwidget.h b/src/gui/editmountpointdialogwidget.h index 6445da4..905f238 100644 --- a/src/gui/editmountpointdialogwidget.h +++ b/src/gui/editmountpointdialogwidget.h @@ -20,6 +20,7 @@ #define EDITMOUNTPOINTDIALOGWIDGET_H #include "ui_editmountpointdialogwidgetbase.h" +#include #include @@ -35,8 +36,6 @@ class QLineEdit; class QPushButton; class QStringList; -class MountEntry; - class EditMountPointDialogWidget : public QWidget, public Ui::EditMountPointDialogWidgetBase { public: @@ -71,8 +70,11 @@ public: QRadioButton& radioDeviceNode() { return *m_RadioDeviceNode; } + FstabEntryList& fstabEntries() { + return m_fstabEntries; + } - bool acceptChanges(); + void acceptChanges(); bool writeMountpoints(const QString& filename); protected: @@ -87,17 +89,16 @@ private: const std::map& boxOptions() const { return m_BoxOptions; } - bool readMountpoints(const QString& filename); - std::multimap& mountPoints() { - return m_MountPoints; - } + const Partition& partition() const { return m_Partition; } private: + FstabEntryList m_fstabEntries; + FstabEntry *entry; + const Partition& m_Partition; - std::multimap m_MountPoints; QString m_Options; QString m_deviceNode; std::map m_BoxOptions;