1 /*
2     SPDX-FileCopyrightText: 2008-2011 Volker Lanz <vl@fidra.de>
3     SPDX-FileCopyrightText: 2012-2020 Andrius Štikonas <andrius@stikonas.eu>
4     SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
5     SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
6     SPDX-FileCopyrightText: 2017 Pali Rohár <pali.rohar@gmail.com>
7     SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
8     SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
9     SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com>
10     SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com>
11 
12     SPDX-License-Identifier: GPL-3.0-or-later
13 */
14 
15 #include "fs/filesystem.h"
16 #include "core/fstab.h"
17 
18 #include "fs/lvm2_pv.h"
19 
20 #include "backend/corebackend.h"
21 #include "backend/corebackendmanager.h"
22 
23 #include "util/externalcommand.h"
24 #include "util/capacity.h"
25 #include "util/helpers.h"
26 
27 #include <KLocalizedString>
28 
29 #include <QColor>
30 #include <QFile>
31 #include <QFileInfo>
32 #include <QStandardPaths>
33 #include <QStorageInfo>
34 
35 const std::vector<QColor> FileSystem::defaultColorCode =
36 {
37 {
38     QColor( 220,205,175 ), // unknown
39     QColor( 187,249,207 ), // extended
40     QColor( 102,121,150 ), // ext2
41     QColor( 122,145,180 ), // ext3
42     QColor( 143,170,210 ), // ext4
43     QColor( 155,155,130 ), // swap
44     QColor( 204,179,215 ), // fat16
45     QColor( 229,201,240 ), // fat32
46     QColor( 244,214,255 ), // ntfs
47     QColor( 216,220,135 ), // reiser
48     QColor( 251,255,157 ), // reiser4
49     QColor( 200,255,254 ), // xfs
50     QColor( 137,200,198 ), // jfs
51     QColor( 210,136,142 ), // hfs
52     QColor( 240,165,171 ), // hfs+
53     QColor( 151,220,134 ), // ufs
54     QColor( 220,205,175 ), // unformatted
55     QColor( 173,205,255 ), // btrfs
56     QColor( 176,155,185 ), // hpfs
57     QColor( 170,30,77 ),   // luks
58     QColor( 96,140,85 ),   // ocfs2
59     QColor( 33,137,108 ),  // zfs
60     QColor( 250,230,255 ), // exfat
61     QColor( 242,155,104 ), // nilfs2
62     QColor( 160,210,180 ), // lvm2 pv
63     QColor( 255,170,0 ),   // f2fs
64     QColor( 170,120,255 ), // udf
65     QColor( 177,82,69 ),   // iso9660
66     QColor( 223,39,104 ),  // luks2
67     QColor( 204,179,255 ), // fat12
68     QColor( 255,100,100 ), // linux_raid_member
69     QColor( 110,20,50 ),   // bitlocker
70     QColor( 255,155,174 ), // apfs
71     QColor( 0,170,255 ), // minix
72 }
73 };
74 
75 struct FileSystemPrivate {
76     FileSystem::Type m_Type;
77     qint64 m_FirstSector;
78     qint64 m_LastSector;
79     qint64 m_SectorSize;
80     qint64 m_SectorsUsed;
81     QString m_Label;
82     QString m_UUID;
83     QStringList m_AvailableFeatures;
84     QVariantMap m_Features;
85 };
86 
87 /** Creates a new FileSystem object
88     @param firstsector the first sector used by this FileSystem on the Device
89     @param lastsector the last sector used by this FileSystem on the Device
90     @param sectorsused the number of sectors in use on the FileSystem
91     @param label the FileSystem label
92     @param type the FileSystem type
93 */
FileSystem(qint64 firstsector,qint64 lastsector,qint64 sectorsused,const QString & label,FileSystem::Type type)94 FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) :
95     d(std::make_unique<FileSystemPrivate>())
96 {
97     d->m_Type = type;
98     d->m_FirstSector = firstsector;
99     d->m_LastSector = lastsector;
100     d->m_SectorsUsed = sectorsused;
101     d->m_Label = label;
102     d->m_UUID = QString();
103 }
104 
105 /** Creates a new FileSystem object
106     @param firstsector the first sector used by this FileSystem on the Device
107     @param lastsector the last sector used by this FileSystem on the Device
108     @param sectorsused the number of sectors in use on the FileSystem
109     @param label the FileSystem label
110     @param features the FileSystem features
111     @param type the FileSystem type
112 */
FileSystem(qint64 firstsector,qint64 lastsector,qint64 sectorsused,const QString & label,const QVariantMap & features,FileSystem::Type type)113 FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features, FileSystem::Type type) :
114     d(std::make_unique<FileSystemPrivate>())
115 {
116     d->m_Type = type;
117     d->m_FirstSector = firstsector;
118     d->m_LastSector = lastsector;
119     d->m_SectorsUsed = sectorsused;
120     d->m_Label = label;
121     d->m_Features = features;
122     d->m_UUID = QString();
123 }
124 
~FileSystem()125 FileSystem::~FileSystem()
126 {
127 }
128 
129 /** Reads the capacity in use on this FileSystem
130     @param deviceNode the device node for the Partition the FileSystem is on
131     @return the used capacity in bytes or -1 in case of an error
132 */
readUsedCapacity(const QString & deviceNode) const133 qint64 FileSystem::readUsedCapacity(const QString& deviceNode) const
134 {
135     Q_UNUSED(deviceNode)
136 
137     return -1;
138 }
139 
detectFileSystem(const QString & partitionPath)140 FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath)
141 {
142     return CoreBackendManager::self()->backend()->detectFileSystem(partitionPath);
143 }
144 
detectMountPoint(FileSystem * fs,const QString & partitionPath)145 QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPath)
146 {
147     if (fs->type() == FileSystem::Type::Lvm2_PV)
148         return FS::lvm2_pv::getVGName(partitionPath);
149 
150     if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed
151         return QString();
152 
153     QStringList mountPoints;
154     QFileInfo partitionPathFileInfo(partitionPath);
155     QString partitionCanonicalPath = partitionPathFileInfo.canonicalFilePath();
156     const QList<QStorageInfo> mountedVolumes = QStorageInfo::mountedVolumes();
157     for (const QStorageInfo &storage : mountedVolumes) {
158         if (partitionCanonicalPath == QFileInfo(QFile::decodeName(storage.device())).canonicalFilePath() ) {
159             mountPoints.append(storage.rootPath());
160         }
161     }
162 
163     mountPoints.append(possibleMountPoints(partitionPath));
164 
165     return mountPoints.isEmpty() ? QString() : mountPoints.first();
166 }
167 
detectMountStatus(FileSystem * fs,const QString & partitionPath)168 bool FileSystem::detectMountStatus(FileSystem* fs, const QString& partitionPath)
169 {
170     bool mounted = false;
171 
172     if (fs->type() == FileSystem::Type::Lvm2_PV) {
173         mounted = !FS::lvm2_pv::getVGName(partitionPath).isEmpty();
174     } else {
175         mounted = isMounted(partitionPath);
176     }
177     return mounted;
178 }
179 
180 /** Reads the label for this FileSystem
181     @param deviceNode the device node for the Partition the FileSystem is on
182     @return the FileSystem label or an empty string in case of error
183 */
readLabel(const QString & deviceNode) const184 QString FileSystem::readLabel(const QString& deviceNode) const
185 {
186     return CoreBackendManager::self()->backend()->readLabel(deviceNode);
187 }
188 
189 /** Creates a new FileSystem
190     @param report Report to write status information to
191     @param deviceNode the device node for the Partition to create the FileSystem on
192     @return true if successful
193 */
create(Report & report,const QString & deviceNode)194 bool FileSystem::create(Report& report, const QString& deviceNode)
195 {
196     Q_UNUSED(report)
197     Q_UNUSED(deviceNode)
198 
199     return true;
200 }
201 
202 /** Creates a new FileSystem with a specified Label
203     @param report Report to write status information to
204     @param deviceNode the device node for the Partition to create the FileSystem on
205     @param label the new label for the FileSystem
206     @return true if successful
207 */
createWithLabel(Report & report,const QString & deviceNode,const QString & label)208 bool FileSystem::createWithLabel(Report& report, const QString& deviceNode, const QString& label)
209 {
210     Q_UNUSED(report)
211     Q_UNUSED(deviceNode)
212     Q_UNUSED(label)
213 
214     return true;
215 }
216 
217 /** Scans a new FileSystem and load file system specific class variables.
218  *  @param deviceNode the device node for the Partition to create the FileSystem on
219 */
scan(const QString & deviceNode)220 void FileSystem::scan(const QString& deviceNode)
221 {
222     Q_UNUSED(deviceNode)
223 }
224 
225 /** Resize a FileSystem to a given new length
226     @param report Report to write status information to
227     @param deviceNode the device node for the Partition the FileSystem is on
228     @param newLength the new length for the FileSystem in bytes
229     @return true on success
230 */
resize(Report & report,const QString & deviceNode,qint64 newLength) const231 bool FileSystem::resize(Report& report, const QString& deviceNode, qint64 newLength) const
232 {
233     Q_UNUSED(report)
234     Q_UNUSED(deviceNode)
235     Q_UNUSED(newLength)
236 
237     return true;
238 }
239 
240 /** Resize a mounted FileSystem to a given new length
241     @param report Report to write status information to
242     @param deviceNode the device node for the Partition the FileSystem is on
243     @param mountPoint the mount point where FileSystem is mounted on
244     @param newLength the new length for the FileSystem in bytes
245     @return true on success
246 */
resizeOnline(Report & report,const QString & deviceNode,const QString & mountPoint,qint64 newLength) const247 bool FileSystem::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 newLength) const
248 {
249     Q_UNUSED(report)
250     Q_UNUSED(deviceNode)
251     Q_UNUSED(mountPoint)
252     Q_UNUSED(newLength)
253 
254     return true;
255 }
256 
257 /** Move a FileSystem to a new start sector
258     @param report Report to write status information to
259     @param deviceNode the device node for the Partition the FileSystem is on
260     @param newStartSector the new start sector for the FileSystem
261     @return true on success
262 */
move(Report & report,const QString & deviceNode,qint64 newStartSector) const263 bool FileSystem::move(Report& report, const QString& deviceNode, qint64 newStartSector) const
264 {
265     Q_UNUSED(report)
266     Q_UNUSED(deviceNode)
267     Q_UNUSED(newStartSector)
268 
269     return true;
270 }
271 
272 /** Writes a label for the FileSystem to disk
273     @param report Report to write status information to
274     @param deviceNode the device node for the Partition the FileSystem is on
275     @param newLabel the new label for the FileSystem
276     @return true on success
277 */
writeLabel(Report & report,const QString & deviceNode,const QString & newLabel)278 bool FileSystem::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel)
279 {
280     Q_UNUSED(report)
281     Q_UNUSED(deviceNode)
282     Q_UNUSED(newLabel)
283 
284     return true;
285 }
286 
287 /** Writes a label for the FileSystem to disk
288     @param report Report to write status information to
289     @param deviceNode the device node for the Partition the FileSystem is on
290     @param mountPoint the mount point where FileSystem is mounted on
291     @param newLabel the new label for the FileSystem
292     @return true on success
293 */
writeLabelOnline(Report & report,const QString & deviceNode,const QString & mountPoint,const QString & newLabel)294 bool FileSystem::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel)
295 {
296     Q_UNUSED(report)
297     Q_UNUSED(deviceNode)
298     Q_UNUSED(mountPoint)
299     Q_UNUSED(newLabel)
300 
301     return true;
302 }
303 
304 /** Copies a FileSystem from one Partition to another
305     @param report Report to write status information to
306     @param targetDeviceNode device node of the target Partition
307     @param sourceDeviceNode device node of the source Partition
308     @return true on success
309 */
copy(Report & report,const QString & targetDeviceNode,const QString & sourceDeviceNode) const310 bool FileSystem::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const
311 {
312     Q_UNUSED(report)
313     Q_UNUSED(targetDeviceNode)
314     Q_UNUSED(sourceDeviceNode)
315 
316     return true;
317 }
318 
319 /** Backs up a FileSystem to a file
320     @param report Report to write status information to
321     @param sourceDevice Device the source FileSystem is on
322     @param deviceNode device node of the source Partition
323     @param filename name of the file to backup to
324     @return true on success
325 */
backup(Report & report,const Device & sourceDevice,const QString & deviceNode,const QString & filename) const326 bool FileSystem::backup(Report& report, const Device& sourceDevice, const QString& deviceNode, const QString& filename) const
327 {
328     Q_UNUSED(report)
329     Q_UNUSED(sourceDevice)
330     Q_UNUSED(deviceNode)
331     Q_UNUSED(filename)
332 
333     return false;
334 }
335 
336 /** Removes a FileSystem
337     @param report Report to write status information to
338     @param deviceNode the device node for the Partition the FileSystem is on
339     @return true if FileSystem is removed
340 */
remove(Report & report,const QString & deviceNode) const341 bool FileSystem::remove(Report& report, const QString& deviceNode) const
342 {
343     Q_UNUSED(report)
344     Q_UNUSED(deviceNode)
345 
346     return true;
347 }
348 
349 /** Checks a FileSystem for errors
350     @param report Report to write status information to
351     @param deviceNode the device node for the Partition the FileSystem is on
352     @return true if FileSystem is error-free
353 */
check(Report & report,const QString & deviceNode) const354 bool FileSystem::check(Report& report, const QString& deviceNode) const
355 {
356     Q_UNUSED(report)
357     Q_UNUSED(deviceNode)
358 
359     return true;
360 }
361 
362 /** Updates a FileSystem UUID on disk
363     @param report Report to write status information to
364     @param deviceNode the device node for the Partition the FileSystem is on
365     @return true on success
366 */
updateUUID(Report & report,const QString & deviceNode) const367 bool FileSystem::updateUUID(Report& report, const QString& deviceNode) const
368 {
369     Q_UNUSED(report)
370     Q_UNUSED(deviceNode)
371 
372     return true;
373 }
374 
375 /** Returns the FileSystem UUID by calling a FileSystem-specific helper program
376     @param deviceNode the device node for the Partition the FileSystem is on
377     @return the UUID or an empty string if the FileSystem does not support UUIDs
378  */
readUUID(const QString & deviceNode) const379 QString FileSystem::readUUID(const QString& deviceNode) const
380 {
381     return CoreBackendManager::self()->backend()->readUUID(deviceNode);
382 }
383 
384 /** Give implementations of FileSystem a chance to update the boot sector after the
385     file system has been moved or copied.
386     @param report Report to write status information to
387     @param deviceNode the device node for the Partition the FileSystem is on
388     @return true on success
389 */
updateBootSector(Report & report,const QString & deviceNode) const390 bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) const
391 {
392     Q_UNUSED(report)
393     Q_UNUSED(deviceNode)
394 
395     return true;
396 }
397 
398 /** @return the minimum capacity valid for this FileSystem in bytes */
minCapacity() const399 qint64 FileSystem::minCapacity() const
400 {
401     return 8 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
402 }
403 
404 /** @return the maximum capacity valid for this FileSystem in bytes */
maxCapacity() const405 qint64 FileSystem::maxCapacity() const
406 {
407     return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB);
408 }
409 
410 /** @return the maximum label length valid for this FileSystem */
maxLabelLength() const411 int FileSystem::maxLabelLength() const
412 {
413     return 16;
414 }
415 
416 /** Validates the label for this FileSystem
417  * @param parent the parent widget passed to the QObject constructor
418  * @return QValidator to validate the file system label line edit input */
labelValidator(QObject * parent) const419 QValidator* FileSystem::labelValidator(QObject *parent) const
420 {
421     Q_UNUSED(parent)
422     return nullptr;
423 }
424 
425 /** @return this FileSystem's type as printable name */
name(const QStringList & languages) const426 QString FileSystem::name(const QStringList& languages) const
427 {
428     return nameForType(type(), languages);
429 }
430 
type() const431 FileSystem::Type FileSystem::type() const
432 {
433     return d->m_Type;
434 }
435 
436 /** @return a pointer to a QString C array with all FileSystem names */
typeNames()437 static const KLocalizedString* typeNames()
438 {
439     static const KLocalizedString s[] = {
440         kxi18nc("@item filesystem name", "unknown"),
441         kxi18nc("@item filesystem name", "extended"),
442 
443         kxi18nc("@item filesystem name", "ext2"),
444         kxi18nc("@item filesystem name", "ext3"),
445         kxi18nc("@item filesystem name", "ext4"),
446         kxi18nc("@item filesystem name", "linuxswap"),
447         kxi18nc("@item filesystem name", "fat16"),
448         kxi18nc("@item filesystem name", "fat32"),
449         kxi18nc("@item filesystem name", "ntfs"),
450         kxi18nc("@item filesystem name", "reiser"),
451         kxi18nc("@item filesystem name", "reiser4"),
452         kxi18nc("@item filesystem name", "xfs"),
453         kxi18nc("@item filesystem name", "jfs"),
454         kxi18nc("@item filesystem name", "hfs"),
455         kxi18nc("@item filesystem name", "hfsplus"),
456         kxi18nc("@item filesystem name", "ufs"),
457         kxi18nc("@item filesystem name", "unformatted"),
458         kxi18nc("@item filesystem name", "btrfs"),
459         kxi18nc("@item filesystem name", "hpfs"),
460         kxi18nc("@item filesystem name", "luks"),
461         kxi18nc("@item filesystem name", "ocfs2"),
462         kxi18nc("@item filesystem name", "zfs"),
463         kxi18nc("@item filesystem name", "exfat"),
464         kxi18nc("@item filesystem name", "nilfs2"),
465         kxi18nc("@item filesystem name", "lvm2 pv"),
466         kxi18nc("@item filesystem name", "f2fs"),
467         kxi18nc("@item filesystem name", "udf"),
468         kxi18nc("@item filesystem name", "iso9660"),
469         kxi18nc("@item filesystem name", "luks2"),
470         kxi18nc("@item filesystem name", "fat12"),
471         kxi18nc("@item filesystem name", "linux_raid_member"),
472         kxi18nc("@item filesystem name", "BitLocker"),
473         kxi18nc("@item filesystem name", "apfs"),
474         kxi18nc("@item filesystem name", "minix"),
475     };
476 
477     return s;
478 }
479 
480 /** @param t the type to get the name for
481     @return the printable name for the given type
482 */
nameForType(FileSystem::Type t,const QStringList & languages)483 QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages)
484 {
485     Q_ASSERT(t < Type::__lastType);
486 
487     return typeNames()[static_cast<int>(t)].toString(languages);
488 }
489 
490 /** @param s the name to get the type for
491     @return the type for the name or FileSystem::Unknown if not found
492 */
typeForName(const QString & s,const QStringList & languages)493 FileSystem::Type FileSystem::typeForName(const QString& s, const QStringList& languages )
494 {
495     for (quint32 i = 0; i < static_cast<int>(Type::__lastType); i++)
496         if (typeNames()[i].toString(languages) == s)
497             return static_cast<FileSystem::Type>(i);
498 
499     return Type::Unknown;
500 }
501 
502 /** @return a QList of all known types */
types()503 QList<FileSystem::Type> FileSystem::types()
504 {
505     QList<FileSystem::Type> result;
506 
507     int i = static_cast<int>(Type::Ext2); // first "real" filesystem
508     while (i != static_cast<int>(Type::__lastType))
509         result.append(static_cast<FileSystem::Type>(i++));
510 
511     return result;
512 }
513 
514 /** @return printable menu title for mounting this FileSystem */
mountTitle() const515 QString FileSystem::mountTitle() const
516 {
517     return xi18nc("@title:menu", "Mount");
518 }
519 
520 /** @return printable menu title for unmounting this FileSystem */
unmountTitle() const521 QString FileSystem::unmountTitle() const
522 {
523     return xi18nc("@title:menu", "Unmount");
524 }
525 
526 /** Moves a FileSystem to a new start sector.
527     @param newStartSector where the FileSystem should be moved to
528 */
move(qint64 newStartSector)529 void FileSystem::move(qint64 newStartSector)
530 {
531     const qint64 savedLength = length();
532     setFirstSector(newStartSector);
533     setLastSector(newStartSector + savedLength - 1);
534 }
canMount(const QString & deviceNode,const QString & mountPoint) const535 bool FileSystem::canMount(const QString& deviceNode, const QString& mountPoint) const
536 {
537     Q_UNUSED(deviceNode)
538     // cannot mount if we have no mount points
539     return !mountPoint.isEmpty();
540 }
541 
542 /** Attempt to mount this FileSystem on a given mount point
543     @param report the report to write information to
544     @param deviceNode the path to the device that is to be unmounted
545     @param mountPoint the mount point to mount the FileSystem on
546     @return true on success
547 */
mount(Report & report,const QString & deviceNode,const QString & mountPoint)548 bool FileSystem::mount(Report& report, const QString &deviceNode, const QString &mountPoint)
549 {
550     ExternalCommand mountCmd(   report,
551                                 QStringLiteral("mount"),
552                               { QStringLiteral("--verbose"),
553                                 deviceNode,
554                                 mountPoint });
555     if (mountCmd.run() && mountCmd.exitCode() == 0) {
556         return true;
557     }
558     return false;
559 }
560 
561 /** Attempt to unmount this FileSystem
562     @param report the report to write information to
563     @param deviceNode the path to the device that is to be unmounted
564     @return true on success
565  */
unmount(Report & report,const QString & deviceNode)566 bool FileSystem::unmount(Report& report, const QString& deviceNode)
567 {
568     ExternalCommand umountCmd(  report,
569                                 QStringLiteral("umount"),
570                               { QStringLiteral("--verbose"),
571                                 QStringLiteral("--all-targets"),
572                                 deviceNode });
573     if ( umountCmd.run() && umountCmd.exitCode() == 0 )
574         return true;
575     return false;
576 }
577 
firstSector() const578 qint64 FileSystem::firstSector() const
579 {
580     return d->m_FirstSector;
581 }
582 
lastSector() const583 qint64 FileSystem::lastSector() const
584 {
585         return d->m_LastSector;
586 }
587 
findExternal(const QString & cmdName,const QStringList & args,int expectedCode)588 bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode)
589 {
590     QString cmdFullPath = QStandardPaths::findExecutable(cmdName);
591     if (cmdFullPath.isEmpty())
592         cmdFullPath = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
593     if (cmdFullPath.isEmpty())
594         return false;
595 
596     ExternalCommand cmd(cmdFullPath, args);
597     if (!cmd.run())
598         return false;
599 
600     return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode;
601 }
602 
addAvailableFeature(const QString & name)603 void FileSystem::addAvailableFeature(const QString& name)
604 {
605     d->m_AvailableFeatures.append(name);
606 }
607 
addFeature(const QString & name,const QVariant & value)608 void FileSystem::addFeature(const QString& name, const QVariant& value)
609 {
610     d->m_Features.insert(name, value);
611 }
612 
addFeatures(const QVariantMap & features)613 void FileSystem::addFeatures(const QVariantMap& features)
614 {
615     for (const auto& k : features.keys()) {
616         d->m_Features.insert(k, features.value(k));
617     }
618 }
619 
supportToolFound() const620 bool FileSystem::supportToolFound() const
621 {
622     return false;
623 }
624 
supportToolName() const625 FileSystem::SupportTool FileSystem::supportToolName() const
626 {
627     return SupportTool();
628 }
629 
setFirstSector(qint64 s)630 void FileSystem::setFirstSector(qint64 s)
631 {
632     d->m_FirstSector = s;
633 }
634 
setLastSector(qint64 s)635 void FileSystem::setLastSector(qint64 s)
636 {
637     d->m_LastSector = s;
638 }
639 
label() const640 const QString& FileSystem::label() const
641 {
642     return d->m_Label;
643 }
644 
availableFeatures() const645 const QStringList& FileSystem::availableFeatures() const
646 {
647     return d->m_AvailableFeatures;
648 }
649 
features() const650 const QVariantMap& FileSystem::features() const
651 {
652     return d->m_Features;
653 }
654 
sectorSize() const655 qint64 FileSystem::sectorSize() const
656 {
657     return d->m_SectorSize;
658 }
659 
sectorsUsed() const660 qint64 FileSystem::sectorsUsed() const
661 {
662     return d->m_SectorsUsed;
663 }
664 
uuid() const665 const QString& FileSystem::uuid() const
666 {
667     return d->m_UUID;
668 }
669 
setSectorSize(qint64 s)670 void FileSystem::setSectorSize(qint64 s)
671 {
672     d->m_SectorSize = s;
673 }
674 
setSectorsUsed(qint64 s)675 void FileSystem::setSectorsUsed(qint64 s)
676 {
677     d->m_SectorsUsed = s;
678 }
679 
setLabel(const QString & s)680 void FileSystem::setLabel(const QString& s)
681 {
682     d->m_Label = s;
683 }
684 
setUUID(const QString & s)685 void FileSystem::setUUID(const QString& s)
686 {
687     d->m_UUID = s;
688 }
689