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 <<EOF | sfdisk disk.img
	label: gpt
	type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, size=64M
	type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
	EOF
	(...)

	$ sfdisk --part-label disk.img 1 efi
	(...)

	$ sfdisk --part-label disk.img 2 rootfs
	(...)

	$ sfdisk --dump disk.img
	(...)
	disk.img1 : start=        2048, size=      131072, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=D08E5B2A-4649-9F4A-AEA3-6C3048888EAA, name="efi"
	disk.img2 : start=      133120, size=     1963999, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=0BEEFE82-19EA-DC4C-BB6A-27B6DA0C3BD2, name="rootfs"

This commit introduces the new job set-partition-label that is used in
the new-operation to set the label of the partition. The job uses the
newly introduced method setPartitionLabel that is implemented by the
sfdisk and dummy backends.
This commit is contained in:
Gaël PORTAY 2020-03-18 14:24:27 -04:00
parent 59269f63df
commit f585f6c3ad
10 changed files with 200 additions and 0 deletions

View File

@ -103,6 +103,17 @@ public:
*/
virtual bool updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) = 0;
/**
* Set the label of a partition in the partition table (GPT only).
* The label is set in the GPT partition name entry. The partition name is known as PARTLABEL by
* several utilities. The device-manager links the device under /dev/disk/by-partlabel/<label>.
* @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.

View File

@ -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

View File

@ -0,0 +1,86 @@
/*************************************************************************
* Copyright (C) 2020 by Gaël PORTAY <gael.portay@collabora.com> *
* *
* 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 <http://www.gnu.org/licenses/>.*
*************************************************************************/
#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 <KLocalizedString>
#include <memory>
/** 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 <filename>%1</filename> does not support setting names. Job ignored.", partition().deviceNode());
else {
std::unique_ptr<CoreBackendDevice> backendDevice = CoreBackendManager::self()->backend()->openDevice(m_Device);
if (backendDevice) {
std::unique_ptr<CoreBackendPartitionTable> 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 <filename>%1</filename>.", partition().deviceNode());
} else
report->line() << xi18nc("@info:progress", "Could not open partition table on device <filename>%1</filename> to set the system type for partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
} else
report->line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to set the system type for partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
}
jobFinished(*report, rval);
return rval;
}
QString SetPartitionLabelJob::description() const
{
return xi18nc("@info:progress", "Set the label on partition <filename>%1</filename> to \"%2\"", partition().deviceNode(), label());
}

View File

@ -0,0 +1,70 @@
/*************************************************************************
* Copyright (C) 2020 by Gaël PORTAY <gael.portay@collabora.com> *
* *
* 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 <http://www.gnu.org/licenses/>.*
*************************************************************************/
#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 <gael.portay@collabora.com>
*/
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

View File

@ -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) {

View File

@ -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;

View File

@ -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)

View File

@ -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;
};

View File

@ -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());

View File

@ -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;