bool BackupFileSystemJob::run(Report& parent) { bool rval = false; Report* report = jobStarted(parent); if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportFileSystem) rval = sourcePartition().fileSystem().backup(*report, sourceDevice(), sourcePartition().deviceNode(), fileName()); else if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportCore) { CopySourceDevice copySource(sourceDevice(), sourcePartition().fileSystem().firstSector(), sourcePartition().fileSystem().lastSector()); CopyTargetFile copyTarget(fileName(), sourceDevice().logicalSectorSize()); if (!copySource.open()) report->line() << i18nc("@info/plain", "Could not open file system on source partition <filename>%1</filename> for backup.", sourcePartition().deviceNode()); else if (!copyTarget.open()) report->line() << i18nc("@info/plain", "Could not create backup file <filename>%1</filename>.", fileName()); else rval = copyBlocks(*report, copyTarget, copySource); } jobFinished(*report, rval); return rval; }
bool LibPartedPartitionTable::resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) { bool rval = false; #if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT if (PedGeometry* originalGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), partition.fileSystem().length())) { if (PedFileSystem* pedFileSystem = ped_file_system_open(originalGeometry)) { if (PedGeometry* resizedGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), newLength)) { PedTimer* pedTimer = ped_timer_new(pedTimerHandler, nullptr); rval = ped_file_system_resize(pedFileSystem, resizedGeometry, pedTimer); ped_timer_destroy(pedTimer); if (!rval) report.line() << xi18nc("@info:progress", "Could not resize file system on partition <filename>%1</filename>.", partition.deviceNode()); ped_geometry_destroy(resizedGeometry); } else report.line() << xi18nc("@info:progress", "Could not get geometry for resized partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); ped_file_system_close(pedFileSystem); } else report.line() << xi18nc("@info:progress", "Could not open partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); ped_geometry_destroy(originalGeometry); } else report.line() << xi18nc("@info:progress", "Could not read geometry for partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); #else Q_UNUSED(report); Q_UNUSED(partition); Q_UNUSED(newLength); #endif return rval; }
bool LibPartedDevice::createPartitionTable(Report& report, const PartitionTable& ptable) { PedDiskType* pedDiskType = ped_disk_type_get(ptable.typeName().toLatin1().constData()); if (pedDiskType == nullptr) { report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not retrieve partition table type \"%1\" for <filename>%2</filename>.", ptable.typeName(), deviceNode()); return false; } PedDevice* dev = ped_device_get(deviceNode().toLatin1().constData()); if (dev == nullptr) { report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not open backend device <filename>%1</filename>.", deviceNode()); return false; } PedDisk* disk = ped_disk_new_fresh(dev, pedDiskType); if (disk == nullptr) { report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not create a new partition table in the backend for device <filename>%1</filename>.", deviceNode()); return false; } return LibPartedPartitionTable::commit(disk); }
bool LibPartedPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) { Q_ASSERT(partition.devicePath() == QString::fromUtf8(pedDevice()->path)); bool rval = false; PedPartition* pedPartition = (partition.roles().has(PartitionRole::Extended)) ? ped_disk_extended_partition(pedDisk()) : ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); if (pedPartition) { if (PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), sector_start, sector_end - sector_start + 1)) { if (PedConstraint* pedConstraint = ped_constraint_exact(pedGeometry)) { if (ped_disk_set_partition_geom(pedDisk(), pedPartition, pedConstraint, sector_start, sector_end)) rval = true; else report.line() << xi18nc("@info:progress", "Could not set geometry for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); ped_constraint_destroy(pedConstraint); } else report.line() << xi18nc("@info:progress", "Could not get constraint for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); ped_geometry_destroy(pedGeometry); } else report.line() << xi18nc("@info:progress", "Could not get geometry for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); } else report.line() << xi18nc("@info:progress", "Could not open partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); return rval; }
bool LibPartedPartitionTable::clobberFileSystem(Report& report, const Partition& partition) { bool rval = false; if (PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector())) { if (pedPartition->type == PED_PARTITION_NORMAL || pedPartition->type == PED_PARTITION_LOGICAL) { if (ped_device_open(pedDevice())) { //reiser4 stores "ReIsEr4" at sector 128 with a sector size of 512 bytes // We need to use memset instead of = {0} because clang sucks. const long long zeroes_length = pedDevice()->sector_size*129; char zeroes[zeroes_length]; memset(zeroes, 0, zeroes_length*sizeof(char)); rval = ped_geometry_write(&pedPartition->geom, zeroes, 0, 129); if (!rval) report.line() << xi18nc("@info:progress", "Failed to erase filesystem signature on partition <filename>%1</filename>.", partition.deviceNode()); ped_device_close(pedDevice()); } } else rval = true; } else report.line() << xi18nc("@info:progress", "Could not delete file system on partition <filename>%1</filename>: Failed to get partition.", partition.deviceNode()); return rval; }
bool ResizeFileSystemJob::resizeFileSystemBackend(Report& report) { bool rval = false; CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device().deviceNode()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { connect(CoreBackendManager::self()->backend(), SIGNAL(progress(int)), this, SIGNAL(progress(int))); rval = backendPartitionTable->resizeFileSystem(report, partition(), newLength()); disconnect(CoreBackendManager::self()->backend(), SIGNAL(progress(int)), this, SIGNAL(progress(int))); if (rval) { report.line() << i18nc("@info/plain", "Successfully resized file system using internal backend functions."); backendPartitionTable->commit(); } delete backendPartitionTable; } else report.line() << i18nc("@info/plain", "Could not open partition <filename>%1</filename> while trying to resize the file system.", partition().deviceNode()); delete backendDevice; }
bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) const { Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; qint64 payloadLength = newLength - payloadOffset(); if ( newLength - length() * m_logicalSectorSize > 0 ) { ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) return m_innerFs->resize(report, mapperName(), payloadLength); } else if (m_innerFs->resize(report, mapperName(), payloadLength)) { ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("--size"), QString::number(payloadLength / m_logicalSectorSize), // LUKS assumes 512 bytes sector QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) return true; } report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition <filename>%1</filename> failed.", deviceNode); return false; }
QString LibPartedPartitionTable::createPartition(Report& report, const Partition& partition) { Q_ASSERT(partition.devicePath() == QString::fromUtf8(pedDevice()->path)); QString rval = QString(); // According to libParted docs, PedPartitionType can be "nullptr if unknown". That's obviously wrong, // it's a typedef for an enum. So let's use something the libparted devs will hopefully never // use... PedPartitionType pedType = static_cast<PedPartitionType>(0xffffffff); if (partition.roles().has(PartitionRole::Extended)) pedType = PED_PARTITION_EXTENDED; else if (partition.roles().has(PartitionRole::Logical)) pedType = PED_PARTITION_LOGICAL; else if (partition.roles().has(PartitionRole::Primary)) pedType = PED_PARTITION_NORMAL; if (pedType == static_cast<int>(0xffffffff)) { report.line() << xi18nc("@info:progress", "Unknown partition role for new partition <filename>%1</filename> (roles: %2)", partition.deviceNode(), partition.roles().toString()); return QString(); } PedFileSystemType* pedFsType = (partition.roles().has(PartitionRole::Extended) || partition.fileSystem().type() == FileSystem::Unformatted) ? nullptr : getPedFileSystemType(partition.fileSystem().type()); PedPartition* pedPartition = ped_partition_new(pedDisk(), pedType, pedFsType, partition.firstSector(), partition.lastSector()); if (pedPartition == nullptr) { report.line() << xi18nc("@info:progress", "Failed to create new partition <filename>%1</filename>.", partition.deviceNode()); return QString(); } PedConstraint* pedConstraint = nullptr; PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), partition.firstSector(), partition.length()); if (pedGeometry) pedConstraint = ped_constraint_exact(pedGeometry); ped_geometry_destroy(pedGeometry); if (pedConstraint == nullptr) { report.line() << i18nc("@info:progress", "Failed to create a new partition: could not get geometry for constraint."); return QString(); } if (ped_disk_add_partition(pedDisk(), pedPartition, pedConstraint)) { char *pedPath = ped_partition_get_path(pedPartition); rval = QString::fromUtf8(pedPath); free(pedPath); } else { report.line() << xi18nc("@info:progress", "Failed to add partition <filename>%1</filename> to device <filename>%2</filename>.", partition.deviceNode(), QString::fromUtf8(pedDisk()->dev->path)); report.line() << LibPartedBackend::lastPartedExceptionMessage(); } ped_constraint_destroy(pedConstraint); return rval; }
bool ResizeFileSystemJob::run(Report& parent) { Q_ASSERT(partition().fileSystem().firstSector() != -1); Q_ASSERT(partition().fileSystem().lastSector() != -1); Q_ASSERT(newLength() <= partition().length()); if (partition().fileSystem().firstSector() == -1 || partition().fileSystem().lastSector() == -1 || newLength() > partition().length()) { kWarning() << "file system first sector: " << partition().fileSystem().firstSector() << ", last sector: " << partition().fileSystem().lastSector() << ", new length: " << newLength() << ", partition length: " << partition().length(); return false; } bool rval = false; Report* report = jobStarted(parent); if (partition().fileSystem().length() == newLength()) { report->line() << i18ncp("@info/plain", "The file system on partition <filename>%2</filename> already has the requested length of 1 sector.", "The file system on partition <filename>%2</filename> already has the requested length of %1 sectors.", newLength(), partition().deviceNode()); rval = true; } else { report->line() << i18nc("@info/plain", "Resizing file system from %1 to %2 sectors.", partition().fileSystem().length(), newLength()); FileSystem::CommandSupportType support = (newLength() < partition().fileSystem().length()) ? partition().fileSystem().supportShrink() : partition().fileSystem().supportGrow(); switch(support) { case FileSystem::cmdSupportBackend: { Report* childReport = report->newChild(); childReport->line() << i18nc("@info/plain", "Resizing a %1 file system using internal backend functions.", partition().fileSystem().name()); rval = resizeFileSystemBackend(*childReport); break; } case FileSystem::cmdSupportFileSystem: { const qint64 newLengthInByte = Capacity(newLength() * device().logicalSectorSize()).toInt(Capacity::Byte); rval = partition().fileSystem().resize(*report, partition().deviceNode(), newLengthInByte); break; } default: report->line() << i18nc("@info/plain", "The file system on partition <filename>%1</filename> cannot be resized because there is no support for it.", partition().deviceNode()); break; } if (rval) partition().fileSystem().setLastSector(partition().fileSystem().firstSector() + newLength() - 1); } jobFinished(*report, rval); return rval; }
bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource) { if (!origSource.overlaps(origTarget)) { report.line() << i18nc("@info/plain", "Source and target for copying do not overlap: Rollback is not required."); return true; } try { CopySourceDevice& csd = dynamic_cast<CopySourceDevice&>(origSource); CopyTargetDevice& ctd = dynamic_cast<CopyTargetDevice&>(origTarget); // default: use values as if we were copying from front to back. qint64 undoSourceFirstSector = origTarget.firstSector(); qint64 undoSourceLastSector = origTarget.firstSector() + origTarget.sectorsWritten() - 1; qint64 undoTargetFirstSector = origSource.firstSector(); qint64 undoTargetLastSector = origSource.firstSector() + origTarget.sectorsWritten() - 1; if (origTarget.firstSector() > origSource.firstSector()) { // we were copying from back to front undoSourceFirstSector = origTarget.firstSector() + origSource.length() - origTarget.sectorsWritten(); undoSourceLastSector = origTarget.firstSector() + origSource.length() - 1; undoTargetFirstSector = origSource.lastSector() - origTarget.sectorsWritten() + 1; undoTargetLastSector = origSource.lastSector(); } report.line() << i18nc("@info/plain", "Rollback from: First sector: %1, last sector: %2.", undoSourceFirstSector, undoSourceLastSector); report.line() << i18nc("@info/plain", "Rollback to: First sector: %1, last sector: %2.", undoTargetFirstSector, undoTargetLastSector); CopySourceDevice undoSource(ctd.device(), undoSourceFirstSector, undoSourceLastSector); if (!undoSource.open()) { report.line() << i18nc("@info/plain", "Could not open device <filename>%1</filename> to rollback copying.", ctd.device().deviceNode()); return false; } CopyTargetDevice undoTarget(csd.device(), undoTargetFirstSector, undoTargetLastSector); if (!undoTarget.open()) { report.line() << i18nc("@info/plain", "Could not open device <filename>%1</filename> to rollback copying.", csd.device().deviceNode()); return false; } return copyBlocks(report, undoTarget, undoSource); } catch ( ... ) { report.line() << i18nc("@info/plain", "Rollback failed: Source or target are not devices."); } return false; }
bool RestoreOperation::execute(Report& parent) { bool rval = false; bool warning = false; Report* report = parent.newChild(description()); if (overwrittenPartition()) restorePartition().setPartitionPath(overwrittenPartition()->devicePath()); if (overwrittenPartition() || (rval = createPartitionJob()->run(*report))) { restorePartition().setState(Partition::StateNone); if ((rval = restoreJob()->run(*report))) { if ((rval = checkTargetJob()->run(*report))) { // If the partition was written over an existing one, the partition itself may now // be larger than the filesystem, so maximize the filesystem to the partition's size // or the image length, whichever is larger. If this fails, don't return an error, just // warn the user. if ((warning = !maximizeJob()->run(*report))) report->line() << xi18nc("@info/plain", "Warning: Maximizing file system on target partition <filename>%1</filename> to the size of the partition failed.", restorePartition().deviceNode()); } else report->line() << xi18nc("@info/plain", "Checking target file system on partition <filename>%1</filename> after the restore failed.", restorePartition().deviceNode()); } else { if (!overwrittenPartition()) DeletePartitionJob(targetDevice(), restorePartition()).run(*report); report->line() << i18nc("@info/plain", "Restoring file system failed."); } } else report->line() << i18nc("@info/plain", "Creating the destination partition to restore to failed."); if (rval) setStatus(warning ? StatusFinishedWarning : StatusFinishedSuccess); else setStatus(StatusError); report->setStatus(i18nc("@info/plain status (success, error, warning...) of operation", "%1: %2", description(), statusText())); return rval; }
bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const { report.line() << xi18nc("@info:progress", "Updating boot sector for NTFS file system on partition <filename>%1</filename>.", deviceNode); quint32 n = firstSector(); char* s = reinterpret_cast<char*>(&n); #if Q_BYTE_ORDER == Q_BIG_ENDIAN std::swap(s[0], s[3]); std::swap(s[1], s[2]); #endif QFile device(deviceNode); if (!device.open(QFile::ReadWrite | QFile::Unbuffered)) { Log() << xi18nc("@info:progress", "Could not open partition <filename>%1</filename> for writing when trying to update the NTFS boot sector.", deviceNode); return false; } if (!device.seek(0x1c)) { Log() << xi18nc("@info:progress", "Could not seek to position 0x1c on partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode); return false; } if (device.write(s, 4) != 4) { Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode); return false; } Log() << xi18nc("@info:progress", "Updated NTFS boot sector for partition <filename>%1</filename> successfully.", deviceNode); return true; }
bool LibPartedPartitionTable::setPartitionSystemType(Report& report, const Partition& partition) { PedFileSystemType* pedFsType = (partition.roles().has(PartitionRole::Extended) || partition.fileSystem().type() == FileSystem::Unformatted) ? nullptr : getPedFileSystemType(partition.fileSystem().type()); if (pedFsType == nullptr) { report.line() << xi18nc("@info:progress", "Could not update the system type for partition <filename>%1</filename>.", partition.deviceNode()); report.line() << xi18nc("@info:progress", "No file system defined."); return false; } PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); if (pedPartition == nullptr) { report.line() << xi18nc("@info:progress", "Could not update the system type for partition <filename>%1</filename>.", partition.deviceNode()); report.line() << xi18nc("@info:progress", "No partition found at sector %1.", partition.firstSector()); return false; } return ped_partition_set_system(pedPartition, pedFsType) != 0; }
bool MoveFileSystemJob::rollbackCopyBlocks( Report& report, CopyTargetDevice& origTarget, CopySourceDevice& origSource ) { if ( !origSource.overlaps( origTarget ) ) { report.line() << tr( "Source and target for copying do not overlap: Rollback is not required." ); return true; } // default: use values as if we were copying from front to back. qint64 undoSourceFirstSector = origTarget.firstSector(); qint64 undoSourceLastSector = origTarget.firstSector() + origTarget.sectorsWritten() - 1; qint64 undoTargetFirstSector = origSource.firstSector(); qint64 undoTargetLastSector = origSource.firstSector() + origTarget.sectorsWritten() - 1; if ( origTarget.firstSector() > origSource.firstSector() ) { // we were copying from back to front undoSourceFirstSector = origTarget.firstSector() + origSource.length() - origTarget.sectorsWritten(); undoSourceLastSector = origTarget.firstSector() + origSource.length() - 1; undoTargetFirstSector = origSource.lastSector() - origTarget.sectorsWritten() + 1; undoTargetLastSector = origSource.lastSector(); } CopySourceDevice undoSource( origTarget.device(), undoSourceFirstSector, undoSourceLastSector ); if ( !undoSource.open() ) { report.line() << tr( "Could not open device %1 to rollback copying." ) .arg( origTarget.device().deviceNode() ); return false; } CopyTargetDevice undoTarget( origSource.device(), undoTargetFirstSector, undoTargetLastSector ); if ( !undoTarget.open() ) { report.line() << tr( "Could not open device %1 to rollback copying." ) .arg( origSource.device().deviceNode() ); return false; } return copyBlocks( report, undoTarget, undoSource ); }
bool CreatePartitionJob::run(Report& parent) { Q_ASSERT(partition().devicePath() == device().deviceNode()); bool rval = false; Report* report = jobStarted(parent); CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device().deviceNode()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { QString partitionPath = backendPartitionTable->createPartition(*report, partition()); if (partitionPath != QString()) { rval = true; partition().setPartitionPath(partitionPath); partition().setState(Partition::StateNone); backendPartitionTable->commit(); } else report->line() << xi18nc("@info/plain", "Failed to add partition <filename>%1</filename> to device <filename>%2</filename>.", partition().deviceNode(), device().deviceNode()); delete backendPartitionTable; } else report->line() << xi18nc("@info/plain", "Could not open partition table on device <filename>%1</filename> to create new partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode()); delete backendDevice; } else report->line() << xi18nc("@info/plain", "Could not open device <filename>%1</filename> to create new partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode()); jobFinished(*report, rval); return rval; }
bool LibPartedPartitionTable::deletePartition(Report& report, const Partition& partition) { Q_ASSERT(partition.devicePath() == QString::fromUtf8(pedDevice()->path)); bool rval = false; PedPartition* pedPartition = partition.roles().has(PartitionRole::Extended) ? ped_disk_extended_partition(pedDisk()) : ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); if (pedPartition) { rval = ped_disk_delete_partition(pedDisk(), pedPartition); if (!rval) report.line() << xi18nc("@info:progress", "Could not delete partition <filename>%1</filename>.", partition.deviceNode()); } else report.line() << xi18nc("@info:progress", "Deleting partition failed: Partition to delete (<filename>%1</filename>) not found on disk.", partition.deviceNode()); return rval; }
bool SetPartFlagsJob::run(Report& parent) { bool rval = true; Report* report = jobStarted(parent); CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device().deviceNode()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { CoreBackendPartition* backendPartition = (partition().roles().has(PartitionRole::Extended)) ? backendPartitionTable->getExtendedPartition() : backendPartitionTable->getPartitionBySector(partition().firstSector()); if (backendPartition) { quint32 count = 0; foreach(const PartitionTable::Flag & f, PartitionTable::flagList()) { emit progress(++count); const bool state = (flags() & f) ? true : false; if (!backendPartition->setFlag(*report, f, state)) { report->line() << xi18nc("@info:progress", "There was an error setting flag %1 for partition <filename>%2</filename> to state %3.", PartitionTable::flagName(f), partition().deviceNode(), state ? xi18nc("@info:progress flag turned on, active", "on") : xi18nc("@info:progress flag turned off, inactive", "off")); rval = false; } } delete backendPartition; } else report->line() << xi18nc("@info:progress", "Could not find partition <filename>%1</filename> on device <filename>%2</filename> to set partition flags.", partition().deviceNode(), device().deviceNode()); if (rval) backendPartitionTable->commit(); delete backendPartitionTable; } else
FileSystem::Type LibPartedPartitionTable::detectFileSystemBySector(Report& report, const Device& device, qint64 sector) { PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), sector); char* pedPath = ped_partition_get_path(pedPartition); FileSystem::Type type = FileSystem::Unknown; if (pedPartition && pedPath) type = CoreBackendManager::self()->backend()->detectFileSystem(QString::fromUtf8(pedPath)); else report.line() << xi18nc("@info:progress", "Could not determine file system of partition at sector %1 on device <filename>%2</filename>.", sector, device.deviceNode()); free(pedPath); return type; }
bool CreateFileSystemJob::run(Report& parent) { bool rval = false; Report* report = jobStarted(parent); if (partition().fileSystem().type() == FileSystem::Unformatted) return true; if (partition().fileSystem().supportCreate() == FileSystem::cmdSupportFileSystem) { if (partition().fileSystem().create(*report, partition().deviceNode())) { CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device().deviceNode()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { if (backendPartitionTable->setPartitionSystemType(*report, partition())) { rval = true; 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()); delete backendPartitionTable; } 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()); delete backendDevice; } 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; }
bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) { /** @todo copyBlocks() assumes that source.sectorSize() == target.sectorSize(). */ if (source.sectorSize() != target.sectorSize()) { report.line() << i18nc("@info/plain", "The logical sector sizes in the source and target for copying are not the same. This is currently unsupported."); return false; } bool rval = true; const qint64 blockSize = 16065 * 8; // number of sectors per block to copy const qint64 blocksToCopy = source.length() / blockSize; qint64 readOffset = source.firstSector(); qint64 writeOffset = target.firstSector(); qint32 copyDir = 1; if (target.firstSector() > source.firstSector()) { readOffset = source.firstSector() + source.length() - blockSize; writeOffset = target.firstSector() + source.length() - blockSize; copyDir = -1; } report.line() << i18nc("@info/plain", "Copying %1 blocks (%2 sectors) from %3 to %4, direction: %5.", blocksToCopy, source.length(), readOffset, writeOffset, copyDir); qint64 blocksCopied = 0; void* buffer = malloc(blockSize * source.sectorSize()); int percent = 0; QTime t; t.start(); while (blocksCopied < blocksToCopy) { if (!(rval = source.readSectors(buffer, readOffset + blockSize * blocksCopied * copyDir, blockSize))) break; if (!(rval = target.writeSectors(buffer, writeOffset + blockSize * blocksCopied * copyDir, blockSize))) break; if (++blocksCopied * 100 / blocksToCopy != percent) { percent = blocksCopied * 100 / blocksToCopy; if (percent % 5 == 0 && t.elapsed() > 1000) { const qint64 mibsPerSec = (blocksCopied * blockSize * source.sectorSize() / 1024 / 1024) / (t.elapsed() / 1000); const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; report.line() << i18nc("@info/plain", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); } emit progress(percent); } } const qint64 lastBlock = source.length() % blockSize; // copy the remainder if (rval && lastBlock > 0) { Q_ASSERT(lastBlock < blockSize); if (lastBlock >= blockSize) kWarning() << "lastBlock: " << lastBlock << ", blockSize: " << blockSize; const qint64 lastBlockReadOffset = copyDir > 0 ? readOffset + blockSize * blocksCopied : source.firstSector(); const qint64 lastBlockWriteOffset = copyDir > 0 ? writeOffset + blockSize * blocksCopied : target.firstSector(); report.line() << i18nc("@info/plain", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); rval = source.readSectors(buffer, lastBlockReadOffset, lastBlock); if (rval) rval = target.writeSectors(buffer, lastBlockWriteOffset, lastBlock); if (rval) emit progress(100); } free(buffer); report.line() << i18ncp("@info/plain argument 2 is a string such as 7 sectors (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 sector", "%1 sectors", target.sectorsWritten())); return rval; }
bool CreatePartitionJob::run(Report& parent) { Q_ASSERT(partition().devicePath() == device().deviceNode()); bool rval = false; Report* report = jobStarted(parent); // According to libParted docs, PedPartitionType can be "NULL if unknown". That's obviously wrong, // it's a typedef for an enum. So let's use something the libparted devs will hopefully never // use... PedPartitionType pedType = static_cast<PedPartitionType>(0xffffffff); if (partition().roles().has(PartitionRole::Extended)) pedType = PED_PARTITION_EXTENDED; else if (partition().roles().has(PartitionRole::Logical)) pedType = PED_PARTITION_LOGICAL; else if (partition().roles().has(PartitionRole::Primary)) pedType = PED_PARTITION_NORMAL; if (pedType == static_cast<int>(0xffffffff)) { report->line() << i18nc("@info/plain", "Unknown partition role for new partition <filename>%1</filename> (roles: %2)", partition().deviceNode(), partition().roles().toString()); } else if (openPed(device().deviceNode())) { PedFileSystemType* pedFsType = (partition().roles().has(PartitionRole::Extended) || partition().fileSystem().type() == FileSystem::Unformatted) ? NULL : getPedFileSystemType(partition().fileSystem().type()); PedPartition* pedPartition = ped_partition_new(pedDisk(), pedType, pedFsType, partition().firstSector(), partition().lastSector()); if (pedPartition) { PedConstraint* pedConstraint = NULL; PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), partition().firstSector(), partition().length()); if (pedGeometry) pedConstraint = ped_constraint_exact(pedGeometry); if (pedConstraint) { if (ped_disk_add_partition(pedDisk(), pedPartition, pedConstraint) && commit()) { partition().setNumber(pedPartition->num); partition().setState(Partition::StateNone); partition().setFirstSector(pedPartition->geom.start); partition().setLastSector(pedPartition->geom.end); rval = true; } else report->line() << i18nc("@info/plain", "Failed to add partition <filename>%1</filename> to device <filename>%2</filename>.", partition().deviceNode(), device().deviceNode()); ped_constraint_destroy(pedConstraint); } else report->line() << i18nc("@info/plain", "Failed to create a new partition: could not get geometry for constraint."); } else report->line() << i18nc("@info/plain", "Failed to create new partition <filename>%1</filename>.", partition().deviceNode()); closePed(); } else report->line() << i18nc("@info/plain", "Could not open device <filename>%1</filename> to create new partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode()); jobFinished(*report, rval); return rval; }
bool MoveFileSystemJob::copyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) { /** @todo copyBlocks() assumes that source.sectorSize() == target.sectorSize(). */ if ( source.sectorSize() != target.sectorSize() ) { report.line() << tr( "The logical sector sizes in the source and target for copying are not the same. This is currently unsupported." ); return false; } bool rval = true; const qint64 blockSize = 16065 * 8; // number of sectors per block to copy const qint64 blocksToCopy = source.length() / blockSize; qint64 readOffset = source.firstSector(); qint64 writeOffset = target.firstSector(); qint32 copyDir = 1; if ( target.firstSector() > source.firstSector() ) { readOffset = source.firstSector() + source.length() - blockSize; writeOffset = target.firstSector() + source.length() - blockSize; copyDir = -1; } qint64 blocksCopied = 0; void* buffer = malloc( blockSize * source.sectorSize() ); int percent = 0; while ( blocksCopied < blocksToCopy ) { rval = source.readSectors( buffer, readOffset + blockSize * blocksCopied * copyDir, blockSize ); if ( !rval ) break; rval = target.writeSectors( buffer, writeOffset + blockSize * blocksCopied * copyDir, blockSize ); if ( !rval ) break; if ( ++blocksCopied * 100 / blocksToCopy != percent ) { percent = blocksCopied * 100 / blocksToCopy; progress( qreal( percent ) / 100. ); } } const qint64 lastBlock = source.length() % blockSize; // copy the remainder if ( rval && lastBlock > 0 ) { if ( lastBlock >= blockSize ) cLog() << "warning: lastBlock: " << lastBlock << ", blockSize: " << blockSize; Q_ASSERT( lastBlock < blockSize ); const qint64 lastBlockReadOffset = copyDir > 0 ? readOffset + blockSize * blocksCopied : source.firstSector(); const qint64 lastBlockWriteOffset = copyDir > 0 ? writeOffset + blockSize * blocksCopied : target.firstSector(); rval = source.readSectors( buffer, lastBlockReadOffset, lastBlock ); if ( rval ) rval = target.writeSectors( buffer, lastBlockWriteOffset, lastBlock ); if ( rval ) emit progress( 1.0 ); } free( buffer ); return rval; }