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;
}
Exemple #3
0
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;
	}
Exemple #7
0
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;
}
Exemple #10
0
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;
}
Exemple #12
0
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;
}
Exemple #17
0
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;
}
Exemple #20
0
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;
}