File indexing completed on 2024-05-05 05:48:51
0001 /* 0002 SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org> 0005 SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> 0006 0007 SPDX-License-Identifier: GPL-3.0-or-later 0008 */ 0009 0010 #include "ops/newoperation.h" 0011 0012 #include "core/partition.h" 0013 #include "core/device.h" 0014 #include "core/partitionnode.h" 0015 0016 #include "jobs/createpartitionjob.h" 0017 #include "jobs/createfilesystemjob.h" 0018 #include "jobs/setpartitionlabeljob.h" 0019 #include "jobs/setpartitionuuidjob.h" 0020 #include "jobs/setpartitionattributesjob.h" 0021 #include "jobs/setfilesystemlabeljob.h" 0022 #include "jobs/setpartflagsjob.h" 0023 #include "jobs/checkfilesystemjob.h" 0024 #include "jobs/changepermissionsjob.h" 0025 0026 #include "fs/filesystem.h" 0027 #include "fs/filesystemfactory.h" 0028 0029 #include "util/capacity.h" 0030 0031 #include <QString> 0032 0033 #include <KLocalizedString> 0034 0035 struct NewOperationPrivate 0036 { 0037 NewOperationPrivate(Device& d, Partition* p) : 0038 m_TargetDevice(d), 0039 m_NewPartition(p), 0040 m_CreatePartitionJob(new CreatePartitionJob(d, *p)), 0041 m_SetPartitionLabelJob(nullptr), 0042 m_SetPartitionUUIDJob(nullptr), 0043 m_SetPartitionAttributesJob(nullptr), 0044 m_CreateFileSystemJob(nullptr), 0045 m_SetPartFlagsJob(nullptr), 0046 m_SetFileSystemLabelJob(nullptr), 0047 m_CheckFileSystemJob(nullptr) 0048 { 0049 } 0050 0051 Device& m_TargetDevice; 0052 Partition* m_NewPartition; 0053 CreatePartitionJob* m_CreatePartitionJob; 0054 SetPartitionLabelJob* m_SetPartitionLabelJob; 0055 SetPartitionUUIDJob* m_SetPartitionUUIDJob; 0056 SetPartitionAttributesJob* m_SetPartitionAttributesJob; 0057 CreateFileSystemJob* m_CreateFileSystemJob; 0058 SetPartFlagsJob* m_SetPartFlagsJob; 0059 SetFileSystemLabelJob* m_SetFileSystemLabelJob; 0060 CheckFileSystemJob* m_CheckFileSystemJob; 0061 }; 0062 0063 /** Creates a new NewOperation. 0064 @param d the Device to create a new Partition on 0065 @param p pointer to the new Partition to create. May not be nullptr. 0066 */ 0067 NewOperation::NewOperation(Device& d, Partition* p) : 0068 Operation(), 0069 d_ptr(std::make_unique<NewOperationPrivate>(d, p)) 0070 { 0071 addJob(createPartitionJob()); 0072 0073 if (!p->label().isEmpty()) { 0074 d_ptr->m_SetPartitionLabelJob = new SetPartitionLabelJob(targetDevice(), newPartition(), p->label()); 0075 addJob(setPartitionLabelJob()); 0076 } 0077 0078 if (!p->uuid().isEmpty()) { 0079 d_ptr->m_SetPartitionUUIDJob = new SetPartitionUUIDJob(targetDevice(), newPartition(), p->uuid()); 0080 addJob(setPartitionUUIDJob()); 0081 } 0082 0083 if (p->attributes()) { 0084 d_ptr->m_SetPartitionAttributesJob = new SetPartitionAttributesJob(targetDevice(), newPartition(), p->attributes()); 0085 addJob(setPartitionAttributesJob()); 0086 } 0087 0088 const FileSystem& fs = newPartition().fileSystem(); 0089 0090 if (fs.type() != FileSystem::Type::Extended) { 0091 // It would seem tempting to skip the CreateFileSystemJob or the 0092 // SetFileSystemLabelJob if either has nothing to do (unformatted FS or 0093 // empty label). However, the user might later on decide to change FS or 0094 // label. The operation stack will merge these operations with this one here 0095 // and if the jobs don't exist things will break. 0096 0097 d_ptr->m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition(), fs.label()); 0098 addJob(createFileSystemJob()); 0099 0100 if (fs.type() == FileSystem::Type::Lvm2_PV) { 0101 d_ptr->m_SetPartFlagsJob = new SetPartFlagsJob(targetDevice(), newPartition(), PartitionTable::Flag::Lvm); 0102 addJob(setPartFlagsJob()); 0103 } 0104 0105 d_ptr->m_SetFileSystemLabelJob = new SetFileSystemLabelJob(newPartition(), fs.label()); 0106 addJob(setLabelJob()); 0107 0108 d_ptr->m_CheckFileSystemJob = new CheckFileSystemJob(newPartition()); 0109 addJob(checkJob()); 0110 0111 // if the user never configured a new permission, nothing will run, if he did, 0112 // then we change the permissions on the newly created partition. 0113 addJob(new ChangePermissionJob(newPartition())); 0114 } 0115 } 0116 0117 NewOperation::~NewOperation() 0118 { 0119 if (status() == StatusPending) 0120 delete d_ptr->m_NewPartition; 0121 } 0122 0123 Partition& NewOperation::newPartition() 0124 { 0125 return *d_ptr->m_NewPartition; 0126 } 0127 0128 const Partition& NewOperation::newPartition() const 0129 { 0130 return *d_ptr->m_NewPartition; 0131 } 0132 0133 Device& NewOperation::targetDevice() 0134 { 0135 return d_ptr->m_TargetDevice; 0136 } 0137 0138 const Device& NewOperation::targetDevice() const 0139 { 0140 return d_ptr->m_TargetDevice; 0141 } 0142 0143 CreatePartitionJob* NewOperation::createPartitionJob() 0144 { 0145 return d_ptr->m_CreatePartitionJob; 0146 } 0147 0148 SetPartitionLabelJob* NewOperation::setPartitionLabelJob() 0149 { 0150 return d_ptr->m_SetPartitionLabelJob; 0151 } 0152 0153 SetPartitionUUIDJob* NewOperation::setPartitionUUIDJob() 0154 { 0155 return d_ptr->m_SetPartitionUUIDJob; 0156 } 0157 0158 SetPartitionAttributesJob* NewOperation::setPartitionAttributesJob() 0159 { 0160 return d_ptr->m_SetPartitionAttributesJob; 0161 } 0162 0163 CreateFileSystemJob* NewOperation::createFileSystemJob() 0164 { 0165 return d_ptr->m_CreateFileSystemJob; 0166 } 0167 0168 SetPartFlagsJob* NewOperation::setPartFlagsJob() 0169 { 0170 return d_ptr->m_SetPartFlagsJob; 0171 } 0172 0173 SetFileSystemLabelJob* NewOperation::setLabelJob() 0174 { 0175 return d_ptr->m_SetFileSystemLabelJob; 0176 } 0177 0178 CheckFileSystemJob* NewOperation::checkJob() 0179 { 0180 return d_ptr->m_CheckFileSystemJob; 0181 } 0182 0183 bool NewOperation::targets(const Device& d) const 0184 { 0185 return d == targetDevice(); 0186 } 0187 0188 bool NewOperation::targets(const Partition& p) const 0189 { 0190 return p == newPartition(); 0191 } 0192 0193 void NewOperation::preview() 0194 { 0195 insertPreviewPartition(targetDevice(), newPartition()); 0196 } 0197 0198 void NewOperation::undo() 0199 { 0200 removePreviewPartition(targetDevice(), newPartition()); 0201 } 0202 0203 QString NewOperation::description() const 0204 { 0205 return xi18nc("@info:status", "Create a new partition (%1, %2) on <filename>%3</filename>", Capacity::formatByteSize(newPartition().capacity()), newPartition().fileSystem().name(), targetDevice().deviceNode()); 0206 } 0207 0208 /** Can a Partition be created somewhere? 0209 @param p the Partition where a new Partition is to be created, may be nullptr 0210 @return true if a new Partition can be created in @p p 0211 */ 0212 bool NewOperation::canCreateNew(const Partition* p) 0213 { 0214 return p != nullptr && p->roles().has(PartitionRole::Unallocated); 0215 } 0216 0217 Partition* NewOperation::createNew(const Partition& cloneFrom, 0218 FileSystem::Type type) 0219 { 0220 Partition* p = new Partition(cloneFrom); 0221 0222 p->deleteFileSystem(); 0223 p->setFileSystem(FileSystemFactory::create(type, 0224 p->firstSector(), 0225 p->lastSector(), 0226 p->sectorSize())); 0227 p->setState(Partition::State::New); 0228 p->setPartitionPath(QString()); 0229 p->setAttributes(0); 0230 0231 return p; 0232 }