File indexing completed on 2024-05-05 05:48:44
0001 /* 0002 SPDX-FileCopyrightText: 2008-2011 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2012-2020 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org> 0005 SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com> 0006 SPDX-FileCopyrightText: 2017 Pali Rohár <pali.rohar@gmail.com> 0007 SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com> 0008 SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net> 0009 SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com> 0010 SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> 0011 0012 SPDX-License-Identifier: GPL-3.0-or-later 0013 */ 0014 0015 #include "fs/filesystem.h" 0016 #include "core/fstab.h" 0017 0018 #include "fs/lvm2_pv.h" 0019 0020 #include "backend/corebackend.h" 0021 #include "backend/corebackendmanager.h" 0022 0023 #include "util/externalcommand.h" 0024 #include "util/externalcommand_trustedprefixes.h" 0025 #include "util/capacity.h" 0026 #include "util/helpers.h" 0027 0028 #include <KLocalizedString> 0029 0030 #include <QColor> 0031 #include <QFile> 0032 #include <QFileInfo> 0033 #include <QStandardPaths> 0034 #include <QStorageInfo> 0035 #include <QTemporaryDir> 0036 0037 const std::vector<QColor> FileSystem::defaultColorCode = 0038 { 0039 { 0040 QColor( 220,205,175 ), // unknown 0041 QColor( 187,249,207 ), // extended 0042 QColor( 102,121,150 ), // ext2 0043 QColor( 122,145,180 ), // ext3 0044 QColor( 143,170,210 ), // ext4 0045 QColor( 155,155,130 ), // swap 0046 QColor( 204,179,215 ), // fat16 0047 QColor( 229,201,240 ), // fat32 0048 QColor( 244,214,255 ), // ntfs 0049 QColor( 216,220,135 ), // reiser 0050 QColor( 251,255,157 ), // reiser4 0051 QColor( 200,255,254 ), // xfs 0052 QColor( 137,200,198 ), // jfs 0053 QColor( 210,136,142 ), // hfs 0054 QColor( 240,165,171 ), // hfs+ 0055 QColor( 151,220,134 ), // ufs 0056 QColor( 220,205,175 ), // unformatted 0057 QColor( 173,205,255 ), // btrfs 0058 QColor( 176,155,185 ), // hpfs 0059 QColor( 170,30,77 ), // luks 0060 QColor( 96,140,85 ), // ocfs2 0061 QColor( 33,137,108 ), // zfs 0062 QColor( 250,230,255 ), // exfat 0063 QColor( 242,155,104 ), // nilfs2 0064 QColor( 160,210,180 ), // lvm2 pv 0065 QColor( 255,170,0 ), // f2fs 0066 QColor( 170,120,255 ), // udf 0067 QColor( 177,82,69 ), // iso9660 0068 QColor( 223,39,104 ), // luks2 0069 QColor( 204,179,255 ), // fat12 0070 QColor( 255,100,100 ), // linux_raid_member 0071 QColor( 110,20,50 ), // bitlocker 0072 QColor( 255,155,174 ), // apfs 0073 QColor( 0,170,255 ), // minix 0074 } 0075 }; 0076 0077 struct FileSystemPrivate { 0078 FileSystem::Type m_Type; 0079 qint64 m_FirstSector; 0080 qint64 m_LastSector; 0081 qint64 m_SectorSize; 0082 qint64 m_SectorsUsed; 0083 QString m_Label; 0084 QString m_UUID; 0085 QString m_posixPermissions; 0086 QStringList m_AvailableFeatures; 0087 QVariantMap m_Features; 0088 }; 0089 0090 /** Creates a new FileSystem object 0091 @param firstsector the first sector used by this FileSystem on the Device 0092 @param lastsector the last sector used by this FileSystem on the Device 0093 @param sectorsused the number of sectors in use on the FileSystem 0094 @param label the FileSystem label 0095 @param type the FileSystem type 0096 */ 0097 FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) : 0098 d(std::make_unique<FileSystemPrivate>()) 0099 { 0100 d->m_Type = type; 0101 d->m_FirstSector = firstsector; 0102 d->m_LastSector = lastsector; 0103 d->m_SectorsUsed = sectorsused; 0104 d->m_Label = label; 0105 d->m_UUID = QString(); 0106 } 0107 0108 /** Creates a new FileSystem object 0109 @param firstsector the first sector used by this FileSystem on the Device 0110 @param lastsector the last sector used by this FileSystem on the Device 0111 @param sectorsused the number of sectors in use on the FileSystem 0112 @param label the FileSystem label 0113 @param features the FileSystem features 0114 @param type the FileSystem type 0115 */ 0116 FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features, FileSystem::Type type) : 0117 d(std::make_unique<FileSystemPrivate>()) 0118 { 0119 d->m_Type = type; 0120 d->m_FirstSector = firstsector; 0121 d->m_LastSector = lastsector; 0122 d->m_SectorsUsed = sectorsused; 0123 d->m_Label = label; 0124 d->m_Features = features; 0125 d->m_UUID = QString(); 0126 } 0127 0128 FileSystem::~FileSystem() 0129 { 0130 } 0131 0132 QString FileSystem::implPosixPermissions() const 0133 { 0134 return d->m_posixPermissions; 0135 } 0136 0137 void FileSystem::implSetPosixPermissions(const QString& permissions) 0138 { 0139 d->m_posixPermissions = permissions; 0140 } 0141 0142 0143 bool FileSystem::execChangePosixPermission(Report& report, const QString& deviceNode) 0144 { 0145 // do nothing if the posix permissions is not used here. 0146 if (d->m_posixPermissions.isEmpty()) { 0147 return true; 0148 } 0149 0150 QTemporaryDir tmpDir; 0151 0152 ExternalCommand mountCmd(report, QStringLiteral("mount"), 0153 { deviceNode, tmpDir.path() }); 0154 0155 bool step = mountCmd.run() && mountCmd.exitCode() == 0; 0156 if (!step) { 0157 return false; 0158 } 0159 0160 ExternalCommand chmodCmd(report, QStringLiteral("chmod"), 0161 // forcing recursive, should be empty but 0162 // programming is weird. 0163 { 0164 d->m_posixPermissions, 0165 tmpDir.path(), 0166 QStringLiteral("--recursive") 0167 }); 0168 0169 const bool chmodStep = chmodCmd.run() && chmodCmd.exitCode() == 0; 0170 0171 ExternalCommand umountCmd(report, QStringLiteral("umount"), 0172 // forcing recursive, should be empty but 0173 // programming is weird. 0174 { 0175 deviceNode, 0176 }); 0177 0178 const bool umountStep = umountCmd.run() && umountCmd.exitCode() == 0; 0179 0180 // we can't return false if chmodStep fails because we still need to umount 0181 // the drive. 0182 if (!chmodStep) { 0183 return false; 0184 } 0185 0186 if (!umountStep) { 0187 return false; 0188 } 0189 0190 return true; 0191 } 0192 0193 /** Reads the capacity in use on this FileSystem 0194 @param deviceNode the device node for the Partition the FileSystem is on 0195 @return the used capacity in bytes or -1 in case of an error 0196 */ 0197 qint64 FileSystem::readUsedCapacity(const QString& deviceNode) const 0198 { 0199 Q_UNUSED(deviceNode) 0200 0201 return -1; 0202 } 0203 0204 FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath) 0205 { 0206 return CoreBackendManager::self()->backend()->detectFileSystem(partitionPath); 0207 } 0208 0209 QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPath) 0210 { 0211 if (fs->type() == FileSystem::Type::Lvm2_PV) 0212 return FS::lvm2_pv::getVGName(partitionPath); 0213 0214 if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed 0215 return QString(); 0216 0217 QStringList mountPoints; 0218 QFileInfo partitionPathFileInfo(partitionPath); 0219 QString partitionCanonicalPath = partitionPathFileInfo.canonicalFilePath(); 0220 const QList<QStorageInfo> mountedVolumes = QStorageInfo::mountedVolumes(); 0221 for (const QStorageInfo &storage : mountedVolumes) { 0222 if (partitionCanonicalPath == QFileInfo(QFile::decodeName(storage.device())).canonicalFilePath() ) { 0223 mountPoints.append(storage.rootPath()); 0224 } 0225 } 0226 0227 mountPoints.append(possibleMountPoints(partitionPath)); 0228 0229 return mountPoints.isEmpty() ? QString() : mountPoints.first(); 0230 } 0231 0232 bool FileSystem::detectMountStatus(FileSystem* fs, const QString& partitionPath) 0233 { 0234 bool mounted = false; 0235 0236 if (fs->type() == FileSystem::Type::Lvm2_PV) { 0237 mounted = !FS::lvm2_pv::getVGName(partitionPath).isEmpty(); 0238 } else { 0239 mounted = isMounted(partitionPath); 0240 } 0241 return mounted; 0242 } 0243 0244 /** Reads the label for this FileSystem 0245 @param deviceNode the device node for the Partition the FileSystem is on 0246 @return the FileSystem label or an empty string in case of error 0247 */ 0248 QString FileSystem::readLabel(const QString& deviceNode) const 0249 { 0250 return CoreBackendManager::self()->backend()->readLabel(deviceNode); 0251 } 0252 0253 /** Creates a new FileSystem 0254 @param report Report to write status information to 0255 @param deviceNode the device node for the Partition to create the FileSystem on 0256 @return true if successful 0257 */ 0258 bool FileSystem::create(Report& report, const QString& deviceNode) 0259 { 0260 Q_UNUSED(report) 0261 Q_UNUSED(deviceNode) 0262 0263 return true; 0264 } 0265 0266 /** Creates a new FileSystem with a specified Label 0267 @param report Report to write status information to 0268 @param deviceNode the device node for the Partition to create the FileSystem on 0269 @param label the new label for the FileSystem 0270 @return true if successful 0271 */ 0272 bool FileSystem::createWithLabel(Report& report, const QString& deviceNode, const QString& label) 0273 { 0274 Q_UNUSED(report) 0275 Q_UNUSED(deviceNode) 0276 Q_UNUSED(label) 0277 0278 return true; 0279 } 0280 0281 /** Scans a new FileSystem and load file system specific class variables. 0282 * @param deviceNode the device node for the Partition to create the FileSystem on 0283 */ 0284 void FileSystem::scan(const QString& deviceNode) 0285 { 0286 Q_UNUSED(deviceNode) 0287 } 0288 0289 /** Resize a FileSystem to a given new length 0290 @param report Report to write status information to 0291 @param deviceNode the device node for the Partition the FileSystem is on 0292 @param newLength the new length for the FileSystem in bytes 0293 @return true on success 0294 */ 0295 bool FileSystem::resize(Report& report, const QString& deviceNode, qint64 newLength) const 0296 { 0297 Q_UNUSED(report) 0298 Q_UNUSED(deviceNode) 0299 Q_UNUSED(newLength) 0300 0301 return true; 0302 } 0303 0304 /** Resize a mounted FileSystem to a given new length 0305 @param report Report to write status information to 0306 @param deviceNode the device node for the Partition the FileSystem is on 0307 @param mountPoint the mount point where FileSystem is mounted on 0308 @param newLength the new length for the FileSystem in bytes 0309 @return true on success 0310 */ 0311 bool FileSystem::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 newLength) const 0312 { 0313 Q_UNUSED(report) 0314 Q_UNUSED(deviceNode) 0315 Q_UNUSED(mountPoint) 0316 Q_UNUSED(newLength) 0317 0318 return true; 0319 } 0320 0321 /** Move a FileSystem to a new start sector 0322 @param report Report to write status information to 0323 @param deviceNode the device node for the Partition the FileSystem is on 0324 @param newStartSector the new start sector for the FileSystem 0325 @return true on success 0326 */ 0327 bool FileSystem::move(Report& report, const QString& deviceNode, qint64 newStartSector) const 0328 { 0329 Q_UNUSED(report) 0330 Q_UNUSED(deviceNode) 0331 Q_UNUSED(newStartSector) 0332 0333 return true; 0334 } 0335 0336 /** Writes a label for the FileSystem to disk 0337 @param report Report to write status information to 0338 @param deviceNode the device node for the Partition the FileSystem is on 0339 @param newLabel the new label for the FileSystem 0340 @return true on success 0341 */ 0342 bool FileSystem::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) 0343 { 0344 Q_UNUSED(report) 0345 Q_UNUSED(deviceNode) 0346 Q_UNUSED(newLabel) 0347 0348 return true; 0349 } 0350 0351 /** Writes a label for the FileSystem to disk 0352 @param report Report to write status information to 0353 @param deviceNode the device node for the Partition the FileSystem is on 0354 @param mountPoint the mount point where FileSystem is mounted on 0355 @param newLabel the new label for the FileSystem 0356 @return true on success 0357 */ 0358 bool FileSystem::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) 0359 { 0360 Q_UNUSED(report) 0361 Q_UNUSED(deviceNode) 0362 Q_UNUSED(mountPoint) 0363 Q_UNUSED(newLabel) 0364 0365 return true; 0366 } 0367 0368 /** Copies a FileSystem from one Partition to another 0369 @param report Report to write status information to 0370 @param targetDeviceNode device node of the target Partition 0371 @param sourceDeviceNode device node of the source Partition 0372 @return true on success 0373 */ 0374 bool FileSystem::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const 0375 { 0376 Q_UNUSED(report) 0377 Q_UNUSED(targetDeviceNode) 0378 Q_UNUSED(sourceDeviceNode) 0379 0380 return true; 0381 } 0382 0383 /** Backs up a FileSystem to a file 0384 @param report Report to write status information to 0385 @param sourceDevice Device the source FileSystem is on 0386 @param deviceNode device node of the source Partition 0387 @param filename name of the file to backup to 0388 @return true on success 0389 */ 0390 bool FileSystem::backup(Report& report, const Device& sourceDevice, const QString& deviceNode, const QString& filename) const 0391 { 0392 Q_UNUSED(report) 0393 Q_UNUSED(sourceDevice) 0394 Q_UNUSED(deviceNode) 0395 Q_UNUSED(filename) 0396 0397 return false; 0398 } 0399 0400 /** Removes a FileSystem 0401 @param report Report to write status information to 0402 @param deviceNode the device node for the Partition the FileSystem is on 0403 @return true if FileSystem is removed 0404 */ 0405 bool FileSystem::remove(Report& report, const QString& deviceNode) const 0406 { 0407 Q_UNUSED(report) 0408 Q_UNUSED(deviceNode) 0409 0410 return true; 0411 } 0412 0413 /** Checks a FileSystem for errors 0414 @param report Report to write status information to 0415 @param deviceNode the device node for the Partition the FileSystem is on 0416 @return true if FileSystem is error-free 0417 */ 0418 bool FileSystem::check(Report& report, const QString& deviceNode) const 0419 { 0420 Q_UNUSED(report) 0421 Q_UNUSED(deviceNode) 0422 0423 return true; 0424 } 0425 0426 /** Updates a FileSystem UUID on disk 0427 @param report Report to write status information to 0428 @param deviceNode the device node for the Partition the FileSystem is on 0429 @return true on success 0430 */ 0431 bool FileSystem::updateUUID(Report& report, const QString& deviceNode) const 0432 { 0433 Q_UNUSED(report) 0434 Q_UNUSED(deviceNode) 0435 0436 return true; 0437 } 0438 0439 /** Returns the FileSystem UUID by calling a FileSystem-specific helper program 0440 @param deviceNode the device node for the Partition the FileSystem is on 0441 @return the UUID or an empty string if the FileSystem does not support UUIDs 0442 */ 0443 QString FileSystem::readUUID(const QString& deviceNode) const 0444 { 0445 return CoreBackendManager::self()->backend()->readUUID(deviceNode); 0446 } 0447 0448 /** Give implementations of FileSystem a chance to update the boot sector after the 0449 file system has been moved or copied. 0450 @param report Report to write status information to 0451 @param deviceNode the device node for the Partition the FileSystem is on 0452 @return true on success 0453 */ 0454 bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) const 0455 { 0456 Q_UNUSED(report) 0457 Q_UNUSED(deviceNode) 0458 0459 return true; 0460 } 0461 0462 /** @return the minimum capacity valid for this FileSystem in bytes */ 0463 qint64 FileSystem::minCapacity() const 0464 { 0465 return 8 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); 0466 } 0467 0468 /** @return the maximum capacity valid for this FileSystem in bytes */ 0469 qint64 FileSystem::maxCapacity() const 0470 { 0471 return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); 0472 } 0473 0474 /** @return the maximum label length valid for this FileSystem */ 0475 int FileSystem::maxLabelLength() const 0476 { 0477 return 16; 0478 } 0479 0480 /** Validates the label for this FileSystem 0481 * @param parent the parent widget passed to the QObject constructor 0482 * @return QValidator to validate the file system label line edit input */ 0483 QValidator* FileSystem::labelValidator(QObject *parent) const 0484 { 0485 Q_UNUSED(parent) 0486 return nullptr; 0487 } 0488 0489 /** @return this FileSystem's type as printable name */ 0490 QString FileSystem::name(const QStringList& languages) const 0491 { 0492 return nameForType(type(), languages); 0493 } 0494 0495 FileSystem::Type FileSystem::type() const 0496 { 0497 return d->m_Type; 0498 } 0499 0500 /** @return a pointer to a QString C array with all FileSystem names */ 0501 static const KLocalizedString* typeNames() 0502 { 0503 static const KLocalizedString s[] = { 0504 kxi18nc("@item filesystem name", "unknown"), 0505 kxi18nc("@item filesystem name", "extended"), 0506 0507 kxi18nc("@item filesystem name", "ext2"), 0508 kxi18nc("@item filesystem name", "ext3"), 0509 kxi18nc("@item filesystem name", "ext4"), 0510 kxi18nc("@item filesystem name", "linuxswap"), 0511 kxi18nc("@item filesystem name", "fat16"), 0512 kxi18nc("@item filesystem name", "fat32"), 0513 kxi18nc("@item filesystem name", "ntfs"), 0514 kxi18nc("@item filesystem name", "reiser"), 0515 kxi18nc("@item filesystem name", "reiser4"), 0516 kxi18nc("@item filesystem name", "xfs"), 0517 kxi18nc("@item filesystem name", "jfs"), 0518 kxi18nc("@item filesystem name", "hfs"), 0519 kxi18nc("@item filesystem name", "hfsplus"), 0520 kxi18nc("@item filesystem name", "ufs"), 0521 kxi18nc("@item filesystem name", "unformatted"), 0522 kxi18nc("@item filesystem name", "btrfs"), 0523 kxi18nc("@item filesystem name", "hpfs"), 0524 kxi18nc("@item filesystem name", "luks"), 0525 kxi18nc("@item filesystem name", "ocfs2"), 0526 kxi18nc("@item filesystem name", "zfs"), 0527 kxi18nc("@item filesystem name", "exfat"), 0528 kxi18nc("@item filesystem name", "nilfs2"), 0529 kxi18nc("@item filesystem name", "lvm2 pv"), 0530 kxi18nc("@item filesystem name", "f2fs"), 0531 kxi18nc("@item filesystem name", "udf"), 0532 kxi18nc("@item filesystem name", "iso9660"), 0533 kxi18nc("@item filesystem name", "luks2"), 0534 kxi18nc("@item filesystem name", "fat12"), 0535 kxi18nc("@item filesystem name", "linux_raid_member"), 0536 kxi18nc("@item filesystem name", "BitLocker"), 0537 kxi18nc("@item filesystem name", "apfs"), 0538 kxi18nc("@item filesystem name", "minix"), 0539 }; 0540 0541 return s; 0542 } 0543 0544 /** @param t the type to get the name for 0545 @return the printable name for the given type 0546 */ 0547 QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages) 0548 { 0549 Q_ASSERT(t < Type::__lastType); 0550 0551 return typeNames()[static_cast<int>(t)].toString(languages); 0552 } 0553 0554 /** @param s the name to get the type for 0555 @return the type for the name or FileSystem::Unknown if not found 0556 */ 0557 FileSystem::Type FileSystem::typeForName(const QString& s, const QStringList& languages ) 0558 { 0559 for (quint32 i = 0; i < static_cast<int>(Type::__lastType); i++) 0560 if (typeNames()[i].toString(languages) == s) 0561 return static_cast<FileSystem::Type>(i); 0562 0563 return Type::Unknown; 0564 } 0565 0566 /** @return a QList of all known types */ 0567 QList<FileSystem::Type> FileSystem::types() 0568 { 0569 QList<FileSystem::Type> result; 0570 0571 int i = static_cast<int>(Type::Ext2); // first "real" filesystem 0572 while (i != static_cast<int>(Type::__lastType)) 0573 result.append(static_cast<FileSystem::Type>(i++)); 0574 0575 return result; 0576 } 0577 0578 /** @return printable menu title for mounting this FileSystem */ 0579 QString FileSystem::mountTitle() const 0580 { 0581 return xi18nc("@title:menu", "Mount"); 0582 } 0583 0584 /** @return printable menu title for unmounting this FileSystem */ 0585 QString FileSystem::unmountTitle() const 0586 { 0587 return xi18nc("@title:menu", "Unmount"); 0588 } 0589 0590 /** Moves a FileSystem to a new start sector. 0591 @param newStartSector where the FileSystem should be moved to 0592 */ 0593 void FileSystem::move(qint64 newStartSector) 0594 { 0595 const qint64 savedLength = length(); 0596 setFirstSector(newStartSector); 0597 setLastSector(newStartSector + savedLength - 1); 0598 } 0599 bool FileSystem::canMount(const QString& deviceNode, const QString& mountPoint) const 0600 { 0601 Q_UNUSED(deviceNode) 0602 // cannot mount if we have no mount points 0603 return !mountPoint.isEmpty(); 0604 } 0605 0606 /** Attempt to mount this FileSystem on a given mount point 0607 @param report the report to write information to 0608 @param deviceNode the path to the device that is to be unmounted 0609 @param mountPoint the mount point to mount the FileSystem on 0610 @return true on success 0611 */ 0612 bool FileSystem::mount(Report& report, const QString &deviceNode, const QString &mountPoint) 0613 { 0614 ExternalCommand mountCmd( report, 0615 QStringLiteral("mount"), 0616 { QStringLiteral("--verbose"), 0617 deviceNode, 0618 mountPoint }); 0619 if (mountCmd.run() && mountCmd.exitCode() == 0) { 0620 return true; 0621 } 0622 return false; 0623 } 0624 0625 /** Attempt to unmount this FileSystem 0626 @param report the report to write information to 0627 @param deviceNode the path to the device that is to be unmounted 0628 @return true on success 0629 */ 0630 bool FileSystem::unmount(Report& report, const QString& deviceNode) 0631 { 0632 ExternalCommand umountCmd( report, 0633 QStringLiteral("umount"), 0634 { QStringLiteral("--verbose"), 0635 QStringLiteral("--all-targets"), 0636 deviceNode }); 0637 if ( umountCmd.run() && umountCmd.exitCode() == 0 ) 0638 return true; 0639 return false; 0640 } 0641 0642 qint64 FileSystem::firstSector() const 0643 { 0644 return d->m_FirstSector; 0645 } 0646 0647 qint64 FileSystem::lastSector() const 0648 { 0649 return d->m_LastSector; 0650 } 0651 0652 bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode) 0653 { 0654 QString cmdFullPath = findTrustedCommand(cmdName); 0655 0656 if (cmdFullPath.isEmpty()) 0657 return false; 0658 0659 ExternalCommand cmd(cmdFullPath, args); 0660 if (!cmd.run()) 0661 return false; 0662 0663 return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode; 0664 } 0665 0666 void FileSystem::addAvailableFeature(const QString& name) 0667 { 0668 d->m_AvailableFeatures.append(name); 0669 } 0670 0671 void FileSystem::addFeature(const QString& name, const QVariant& value) 0672 { 0673 d->m_Features.insert(name, value); 0674 } 0675 0676 void FileSystem::addFeatures(const QVariantMap& features) 0677 { 0678 for (const auto& k : features.keys()) { 0679 d->m_Features.insert(k, features.value(k)); 0680 } 0681 } 0682 0683 bool FileSystem::supportToolFound() const 0684 { 0685 return false; 0686 } 0687 0688 FileSystem::SupportTool FileSystem::supportToolName() const 0689 { 0690 return SupportTool(); 0691 } 0692 0693 void FileSystem::setFirstSector(qint64 s) 0694 { 0695 d->m_FirstSector = s; 0696 } 0697 0698 void FileSystem::setLastSector(qint64 s) 0699 { 0700 d->m_LastSector = s; 0701 } 0702 0703 const QString& FileSystem::label() const 0704 { 0705 return d->m_Label; 0706 } 0707 0708 const QStringList& FileSystem::availableFeatures() const 0709 { 0710 return d->m_AvailableFeatures; 0711 } 0712 0713 const QVariantMap& FileSystem::features() const 0714 { 0715 return d->m_Features; 0716 } 0717 0718 qint64 FileSystem::sectorSize() const 0719 { 0720 return d->m_SectorSize; 0721 } 0722 0723 qint64 FileSystem::sectorsUsed() const 0724 { 0725 return d->m_SectorsUsed; 0726 } 0727 0728 const QString& FileSystem::uuid() const 0729 { 0730 return d->m_UUID; 0731 } 0732 0733 void FileSystem::setSectorSize(qint64 s) 0734 { 0735 d->m_SectorSize = s; 0736 } 0737 0738 void FileSystem::setSectorsUsed(qint64 s) 0739 { 0740 d->m_SectorsUsed = s; 0741 } 0742 0743 void FileSystem::setLabel(const QString& s) 0744 { 0745 d->m_Label = s; 0746 } 0747 0748 void FileSystem::setUUID(const QString& s) 0749 { 0750 d->m_UUID = s; 0751 }