From f585f6c3ada6e5d6748717a17eee8d6a90ea68cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Wed, 18 Mar 2020 14:24:27 -0400 Subject: [PATCH] Add new job to set the GPT partition label The GPT partition layout supports naming partitions. The support for the partition label was added in the backend libparted since commit 28fa6ac (Add support for GTP partition labels). The libparted was removed later by commit 8fa1814 (Remove libparted backend) and no backend sets the partition label. The CLI sfdisk sets the partition label using the option --part-label. See the examples below: $ cat <. + * @param report the report to write information to + * @param partition the partition to set the label for + * @param label the new label for the partition + * @return true on success + */ + virtual bool setPartitionLabel(Report& report, const Partition& partition, const QString& label) = 0; + /** * Set the system type (e.g. 83 for Linux) of a partition. The type to set is taken from * the partition's file system. diff --git a/src/jobs/CMakeLists.txt b/src/jobs/CMakeLists.txt index 908ea9e..aa2665a 100644 --- a/src/jobs/CMakeLists.txt +++ b/src/jobs/CMakeLists.txt @@ -6,6 +6,7 @@ set(JOBS_SRC jobs/shredfilesystemjob.cpp jobs/createpartitionjob.cpp jobs/createpartitiontablejob.cpp + jobs/setpartitionlabeljob.cpp jobs/createvolumegroupjob.cpp jobs/removevolumegroupjob.cpp jobs/deactivatevolumegroupjob.cpp diff --git a/src/jobs/setpartitionlabeljob.cpp b/src/jobs/setpartitionlabeljob.cpp new file mode 100644 index 0000000..6a7fb4e --- /dev/null +++ b/src/jobs/setpartitionlabeljob.cpp @@ -0,0 +1,86 @@ +/************************************************************************* + * Copyright (C) 2020 by Gaël PORTAY * + * * + * 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 3 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 "jobs/setpartitionlabeljob.h" + +#include "backend/corebackend.h" +#include "backend/corebackendmanager.h" +#include "backend/corebackenddevice.h" +#include "backend/corebackendpartitiontable.h" + +#include "core/partition.h" +#include "core/device.h" + +#include "util/report.h" + +#include +#include + +/** Creates a new SetPartitionLabelJob (GPT only) + @param d the Device the Partition to be created will be on + @param p the Partition whose label is to be set is on + @param newLabel the new label +*/ +SetPartitionLabelJob::SetPartitionLabelJob(Device& d, Partition& p, const QString& newLabel) : + Job(), + m_Device(d), + m_Partition(p), + m_Label(newLabel) +{ +} + +bool SetPartitionLabelJob::run(Report& parent) +{ + Q_ASSERT(partition().devicePath() == device().deviceNode()); + + bool rval = true; + + Report* report = jobStarted(parent); + + // The label is supported by GPT only (as partition name), if the partition table is not GPT, + // just ignore the request and say all is well. This helps in operations because + // we don't have to check for support to avoid having a failed job. + if (m_Device.partitionTable()->type() != PartitionTable::gpt) + report->line() << xi18nc("@info:progress", "Partition table of partition %1 does not support setting names. Job ignored.", partition().deviceNode()); + else { + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(m_Device); + if (backendDevice) { + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); + + if (backendPartitionTable) { + if (backendPartitionTable->setPartitionLabel(*report, partition(), m_Label)) { + rval = true; + partition().setLabel(m_Label); + backendPartitionTable->commit(); + } else + report->line() << xi18nc("@info:progress", "Failed to set the system type for the file system on partition %1.", partition().deviceNode()); + } else + report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); + } else + report->line() << xi18nc("@info:progress", "Could not open device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); + + } + + jobFinished(*report, rval); + + return rval; +} + +QString SetPartitionLabelJob::description() const +{ + return xi18nc("@info:progress", "Set the label on partition %1 to \"%2\"", partition().deviceNode(), label()); +} diff --git a/src/jobs/setpartitionlabeljob.h b/src/jobs/setpartitionlabeljob.h new file mode 100644 index 0000000..7c146da --- /dev/null +++ b/src/jobs/setpartitionlabeljob.h @@ -0,0 +1,70 @@ +/************************************************************************* + * Copyright (C) 2020 by Gaël PORTAY * + * * + * 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 3 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 .* + *************************************************************************/ + +#if !defined(KPMCORE_SETPARTITIONNAMEJOB_H) + +#define KPMCORE_SETPARTITIONNAMEJOB_H + +#include "jobs/job.h" + +class Partition; +class Device; +class Report; + +class QString; + +/** Set a Partition label (GPT only). + @author Gaël PORTAY +*/ +class SetPartitionLabelJob : public Job +{ +public: + SetPartitionLabelJob(Device& d, Partition& p, const QString& newLabel); + +public: + bool run(Report& parent) override; + QString description() const override; + +protected: + Partition& partition() { + return m_Partition; + } + const Partition& partition() const { + return m_Partition; + } + + Device& device() { + return m_Device; + } + const Device& device() const { + return m_Device; + } + + const QString& label() const { + return m_Label; + } + void setLabel(const QString& l) { + m_Label = l; + } + +private: + Device& m_Device; + Partition& m_Partition; + QString m_Label; +}; + +#endif diff --git a/src/ops/newoperation.cpp b/src/ops/newoperation.cpp index 40bdc62..c5debd5 100644 --- a/src/ops/newoperation.cpp +++ b/src/ops/newoperation.cpp @@ -24,6 +24,7 @@ #include "jobs/createpartitionjob.h" #include "jobs/createfilesystemjob.h" +#include "jobs/setpartitionlabeljob.h" #include "jobs/setfilesystemlabeljob.h" #include "jobs/setpartflagsjob.h" #include "jobs/checkfilesystemjob.h" @@ -46,6 +47,7 @@ NewOperation::NewOperation(Device& d, Partition* p) : m_TargetDevice(d), m_NewPartition(p), m_CreatePartitionJob(new CreatePartitionJob(targetDevice(), newPartition())), + m_SetPartitionLabelJob(nullptr), m_CreateFileSystemJob(nullptr), m_SetPartFlagsJob(nullptr), m_SetFileSystemLabelJob(nullptr), @@ -53,6 +55,11 @@ NewOperation::NewOperation(Device& d, Partition* p) : { addJob(createPartitionJob()); + if (!p->label().isEmpty()) { + m_SetPartitionLabelJob = new SetPartitionLabelJob(targetDevice(), newPartition(), p->label()); + addJob(setPartitionLabelJob()); + } + const FileSystem& fs = newPartition().fileSystem(); if (fs.type() != FileSystem::Type::Extended) { diff --git a/src/ops/newoperation.h b/src/ops/newoperation.h index 36e9d2b..8f774ba 100644 --- a/src/ops/newoperation.h +++ b/src/ops/newoperation.h @@ -30,6 +30,7 @@ class Device; class OperationStack; class CreatePartitionJob; +class SetPartitionLabelJob; class CreateFileSystemJob; class SetFileSystemLabelJob; class SetPartFlagsJob; @@ -83,6 +84,9 @@ protected: CreatePartitionJob* createPartitionJob() { return m_CreatePartitionJob; } + SetPartitionLabelJob* setPartitionLabelJob() { + return m_SetPartitionLabelJob; + } CreateFileSystemJob* createFileSystemJob() { return m_CreateFileSystemJob; } @@ -100,6 +104,7 @@ private: Device& m_TargetDevice; Partition* m_NewPartition; CreatePartitionJob* m_CreatePartitionJob; + SetPartitionLabelJob* m_SetPartitionLabelJob; CreateFileSystemJob* m_CreateFileSystemJob; SetPartFlagsJob* m_SetPartFlagsJob; SetFileSystemLabelJob* m_SetFileSystemLabelJob; diff --git a/src/plugins/dummy/dummypartitiontable.cpp b/src/plugins/dummy/dummypartitiontable.cpp index 90dd93f..dc4be94 100644 --- a/src/plugins/dummy/dummypartitiontable.cpp +++ b/src/plugins/dummy/dummypartitiontable.cpp @@ -108,6 +108,15 @@ bool DummyPartitionTable::setPartitionSystemType(Report& report, const Partition return true; } +bool DummyPartitionTable::setPartitionLabel(Report& report, const Partition& partition, const QString& label) +{ + Q_UNUSED(report) + Q_UNUSED(partition) + Q_UNUSED(label) + + return true; +} + bool DummyPartitionTable::setFlag(Report& report, const Partition& partition, PartitionTable::Flag partitionManagerFlag, bool state) { Q_UNUSED(report) diff --git a/src/plugins/dummy/dummypartitiontable.h b/src/plugins/dummy/dummypartitiontable.h index 3d1da5b..d5ba513 100644 --- a/src/plugins/dummy/dummypartitiontable.h +++ b/src/plugins/dummy/dummypartitiontable.h @@ -46,6 +46,7 @@ public: bool clobberFileSystem(Report& report, const Partition& partition) override; bool resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) override; FileSystem::Type detectFileSystemBySector(Report& report, const Device& device, qint64 sector) override; + bool setPartitionLabel(Report& report, const Partition& partition, const QString& label) override; bool setPartitionSystemType(Report& report, const Partition& partition) override; bool setFlag(Report& report, const Partition& partition, PartitionTable::Flag partitionManagerFlag, bool state) override; }; diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 5ed36ac..0c2e961 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -213,6 +213,15 @@ static QLatin1String getPartitionType(FileSystem::Type t, PartitionTable::TableT return QLatin1String(); } +bool SfdiskPartitionTable::setPartitionLabel(Report& report, const Partition& partition, const QString& label) +{ + if (label.isEmpty()) + return true; + ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--part-label"), m_device->deviceNode(), QString::number(partition.number()), + label } ); + return sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0; +} + bool SfdiskPartitionTable::setPartitionSystemType(Report& report, const Partition& partition) { QString partitionType = getPartitionType(partition.fileSystem().type(), m_device->partitionTable()->type()); diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.h b/src/plugins/sfdisk/sfdiskpartitiontable.h index 9d0de1e..c16c5ef 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.h +++ b/src/plugins/sfdisk/sfdiskpartitiontable.h @@ -46,6 +46,7 @@ public: bool clobberFileSystem(Report& report, const Partition& partition) override; bool resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) override; FileSystem::Type detectFileSystemBySector(Report& report, const Device& device, qint64 sector) override; + bool setPartitionLabel(Report& report, const Partition& partition, const QString& label) override; bool setPartitionSystemType(Report& report, const Partition& partition) override; bool setFlag(Report& report, const Partition& partition, PartitionTable::Flag flag, bool state) override;