Add new job to set the GPT partition attributes

The GPT partition layout supports partition attributes.

The CLI sfdisk sets the partition attributes using the option
--part-attrs. 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-attrs disk.img 1 RequiredPartition,NoBlockIOProtocol,LegacyBIOSBootable,48
	(...)

	$ sfdisk --part-attrs disk.img 2 60,61,62,63
	(...)

	$ sfdisk --dump disk.img
	(...)
	disk.img1 : start=        2048, size=      131072, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=BBE806BB-8567-A843-9FF5-9B6B35D2908E, attrs="RequiredPartition NoBlockIOProtocol LegacyBIOSBootable GUID:48"
	disk.img2 : start=      133120, size=     1963999, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7DB39F08-C138-664B-B38E-ED2DEB549AA6, attrs="GUID:60,61,62,63"

This commit introduces the new job set-partition-attributes that is used
in the new-operation to set the attributes of the partition. The job
uses the newly introduced method setPartitionAttributes that is
implemented by the sfdisk and dummy backends.

Note: This is a copypaste of what was done for GPT partition label in
commit f585f6c (Add new job to set the GPT partition label) and GPT
partition UUID in commit 1dde035 (Add new job to set the GPT partition
UUID).

Note: RequiredPartition, NoBlockIOProtocol, LegacyBIOSBootable are
key words for 0, 1 and 2.
This commit is contained in:
Gaël PORTAY 2020-05-15 12:24:06 -04:00
parent 9dd118c58b
commit 0ffec31e2b
11 changed files with 220 additions and 1 deletions

View File

@ -135,6 +135,15 @@ public:
*/
virtual bool setPartitionUUID(Report& report, const Partition& partition, const QString& uuid) = 0;
/**
* Set the attributes of a partition in the partition table (GPT only).
* @param report the report to write information to
* @param partition the partition to set the attributes for
* @param attrs the new attributes for the partition
* @return true on success
*/
virtual bool setPartitionAttributes(Report& report, const Partition& partition, quint64 attrs) = 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

@ -24,7 +24,6 @@
#include "util/libpartitionmanagerexport.h"
#include <QStringList>
#include <QtGlobal>
#include <QPointer>
@ -131,6 +130,9 @@ public:
const QString& uuid() const {
return m_UUID; /**< @return the GPT Partition UUID */
}
quint64 attributes() const {
return m_Attributes; /**< @return the GPT Partition attributes */
}
qint64 firstSector() const {
return m_FirstSector; /**< @return the Partition's first sector on the Device */
}
@ -219,6 +221,9 @@ public:
void setUUID(const QString& s) {
m_UUID = s; /**< @param s the new UUID */
}
void setAttributes(quint64 f) {
m_Attributes = f; /**< @param f the new attributes */
}
void append(Partition* p) override {
m_Children.append(p);
@ -274,6 +279,7 @@ private:
QString m_Label;
QString m_Type;
QString m_UUID;
quint64 m_Attributes;
QString m_PartitionPath;
QString m_MountPoint;
PartitionTable::Flags m_AvailableFlags;

View File

@ -8,6 +8,7 @@ set(JOBS_SRC
jobs/createpartitiontablejob.cpp
jobs/setpartitionlabeljob.cpp
jobs/setpartitionuuidjob.cpp
jobs/setpartitionattributesjob.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/setpartitionattributesjob.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 SetPartitionAttributesJob (GPT only)
@param d the Device the Partition to be created will be on
@param p the Partition whose attributes is to be set is on
@param newAttrs the new attributes
*/
SetPartitionAttributesJob::SetPartitionAttributesJob(Device& d, Partition& p, quint64 newAttrs) :
Job(),
m_Device(d),
m_Partition(p),
m_Attributes(newAttrs)
{
}
bool SetPartitionAttributesJob::run(Report& parent)
{
Q_ASSERT(partition().devicePath() == device().deviceNode());
bool rval = true;
Report* report = jobStarted(parent);
// The attributes are supported by GPT only, 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 attributes. 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->setPartitionAttributes(*report, partition(), m_Attributes)) {
rval = true;
partition().setAttributes(m_Attributes);
backendPartitionTable->commit();
} else
report->line() << xi18nc("@info:progress", "Failed to set the attributes for the 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 attributes for the partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
} else
report->line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to set the attributes for partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
}
jobFinished(*report, rval);
return rval;
}
QString SetPartitionAttributesJob::description() const
{
return xi18nc("@info:progress", "Set the attributes on partition <filename>%1</filename> to \"%2\"", partition().deviceNode(), QString::number(attributes(), 0x10));
}

View File

@ -0,0 +1,68 @@
/*************************************************************************
* 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_SETPARTITIONATTRIBUTESJOB_H)
#define KPMCORE_SETPARTITIONATTRIBUTESJOB_H
#include "jobs/job.h"
class Partition;
class Device;
class Report;
/** Set a Partition attributes (GPT only).
@author Gaël PORTAY <gael.portay@collabora.com>
*/
class SetPartitionAttributesJob : public Job
{
public:
SetPartitionAttributesJob(Device& d, Partition& p, quint64 newAttrs);
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;
}
quint64 attributes() const {
return m_Attributes;
}
void setAttributes(quint64 f) {
m_Attributes = f;
}
private:
Device& m_Device;
Partition& m_Partition;
quint64 m_Attributes;
};
#endif

View File

@ -26,6 +26,7 @@
#include "jobs/createfilesystemjob.h"
#include "jobs/setpartitionlabeljob.h"
#include "jobs/setpartitionuuidjob.h"
#include "jobs/setpartitionattributesjob.h"
#include "jobs/setfilesystemlabeljob.h"
#include "jobs/setpartflagsjob.h"
#include "jobs/checkfilesystemjob.h"
@ -50,6 +51,7 @@ NewOperation::NewOperation(Device& d, Partition* p) :
m_CreatePartitionJob(new CreatePartitionJob(targetDevice(), newPartition())),
m_SetPartitionLabelJob(nullptr),
m_SetPartitionUUIDJob(nullptr),
m_SetPartitionAttributesJob(nullptr),
m_CreateFileSystemJob(nullptr),
m_SetPartFlagsJob(nullptr),
m_SetFileSystemLabelJob(nullptr),
@ -67,6 +69,11 @@ NewOperation::NewOperation(Device& d, Partition* p) :
addJob(setPartitionUUIDJob());
}
if (p->attributes()) {
m_SetPartitionAttributesJob = new SetPartitionAttributesJob(targetDevice(), newPartition(), p->attributes());
addJob(setPartitionAttributesJob());
}
const FileSystem& fs = newPartition().fileSystem();
if (fs.type() != FileSystem::Type::Extended) {

View File

@ -32,6 +32,7 @@ class OperationStack;
class CreatePartitionJob;
class SetPartitionLabelJob;
class SetPartitionUUIDJob;
class SetPartitionAttributesJob;
class CreateFileSystemJob;
class SetFileSystemLabelJob;
class SetPartFlagsJob;
@ -91,6 +92,9 @@ protected:
SetPartitionUUIDJob* setPartitionUUIDJob() {
return m_SetPartitionUUIDJob;
}
SetPartitionAttributesJob* setPartitionAttributesJob() {
return m_SetPartitionAttributesJob;
}
CreateFileSystemJob* createFileSystemJob() {
return m_CreateFileSystemJob;
}
@ -110,6 +114,7 @@ private:
CreatePartitionJob* m_CreatePartitionJob;
SetPartitionLabelJob* m_SetPartitionLabelJob;
SetPartitionUUIDJob* m_SetPartitionUUIDJob;
SetPartitionAttributesJob* m_SetPartitionAttributesJob;
CreateFileSystemJob* m_CreateFileSystemJob;
SetPartFlagsJob* m_SetPartFlagsJob;
SetFileSystemLabelJob* m_SetFileSystemLabelJob;

View File

@ -134,6 +134,15 @@ bool DummyPartitionTable::setPartitionUUID(Report& report, const Partition& part
return true;
}
bool DummyPartitionTable::setPartitionAttributes(Report& report, const Partition& partition, quint64 attrs)
{
Q_UNUSED(report)
Q_UNUSED(partition)
Q_UNUSED(attrs)
return true;
}
bool DummyPartitionTable::setFlag(Report& report, const Partition& partition, PartitionTable::Flag partitionManagerFlag, bool state)
{
Q_UNUSED(report)

View File

@ -49,6 +49,7 @@ public:
bool setPartitionLabel(Report& report, const Partition& partition, const QString& label) override;
QString getPartitionUUID(Report& report, const Partition& partition) override;
bool setPartitionUUID(Report& report, const Partition& partition, const QString& uuid) override;
bool setPartitionAttributes(Report& report, const Partition& partition, quint64 attrs) 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,22 @@ static QLatin1String getPartitionType(FileSystem::Type t, PartitionTable::TableT
return QLatin1String();
}
static QStringList getAttributeList(quint64 attrs)
{
QStringList list;
if (attrs & 0x01)
list += QStringLiteral("RequiredPartition");
if (attrs & 0x02)
list += QStringLiteral("NoBlockIOProtocol");
if (attrs & 0x04)
list += QStringLiteral("LegacyBIOSBootable");
for (int bit = 48; bit < 64; bit++)
if (attrs & (1 << bit))
list += QString::number(bit);
return list;
}
bool SfdiskPartitionTable::setPartitionLabel(Report& report, const Partition& partition, const QString& label)
{
if (label.isEmpty())
@ -246,6 +262,16 @@ bool SfdiskPartitionTable::setPartitionUUID(Report& report, const Partition& par
return sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0;
}
bool SfdiskPartitionTable::setPartitionAttributes(Report& report, const Partition& partition, quint64 attrs)
{
QStringList attributes = getAttributeList(attrs);
if (attributes.isEmpty())
return true;
ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--part-attrs"), m_device->deviceNode(), QString::number(partition.number()),
attributes.join(QStringLiteral(",")) } );
return sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0;
}
bool SfdiskPartitionTable::setPartitionSystemType(Report& report, const Partition& partition)
{
QString partitionType = partition.type();

View File

@ -49,6 +49,7 @@ public:
bool setPartitionLabel(Report& report, const Partition& partition, const QString& label) override;
QString getPartitionUUID(Report& report, const Partition& partition) override;
bool setPartitionUUID(Report& report, const Partition& partition, const QString& uuid) override;
bool setPartitionAttributes(Report& report, const Partition& partition, quint64 attrs) override;
bool setPartitionSystemType(Report& report, const Partition& partition) override;
bool setFlag(Report& report, const Partition& partition, PartitionTable::Flag flag, bool state) override;