diff --git a/TODO b/TODO index 3f5b13c..3dc6d02 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,7 @@ Random plans and ideas for 1.1 and beyond: that deals with labels and try to get it out of the package. If that's entirely impossible, maybe a kludge like GParted uses should be considered *shudder* - + * To say it bluntly: libparted is a complete dead end. What we have to do is separate the backend logic from the core and write backend interfaces so partitionmanager can make use of other backends apart from libparted. KDE's @@ -13,11 +13,6 @@ Random plans and ideas for 1.1 and beyond: Also, DeviceKit-disks is around the corner and implementations using it for solid begin to materialize. -* People want mount management (i.e. fstab management) in partition manager. - I've written a small kcm, Mount Manager, as a proof of concept how this could - look like, but I'm not yet happy with it. Eventually, this will / should / - can me merged into partition manager. - * The whole lvm/dm debacle. Nothing much useful can be done about it without the backend stuff mentioned above, though. @@ -28,4 +23,11 @@ Random plans and ideas for 1.1 and beyond: hopefully be able to get meaningful progress status reporting while resizing, checking and so on. - +* Default size of File System Support dialog window. + +* Re-design partition list. Maybe include all disks into the list and drop the + devices panel? + +* Information about file system on a separate tab in the properties, unique + to the file system in use. + diff --git a/src/core/copysourcerandom.cpp b/src/core/copysourcerandom.cpp new file mode 100644 index 0000000..c2626ad --- /dev/null +++ b/src/core/copysourcerandom.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "core/copysourcerandom.h" + +#include + +/** Constructs a CopySourceRandom with the given @p size + @param s the size the copy source will (pretend to) have + @param sectorsize the sectorsize the copy source will (pretend to) have +*/ +CopySourceRandom::CopySourceRandom (qint64 s, qint32 sectorsize) : + CopySource(), + m_Size(s), + m_SectorSize(sectorsize), + m_Random("/dev/urandom") +{ +} + +/** Opens the random source. + @return true on success +*/ +bool CopySourceRandom::open() +{ + return random().open(QIODevice::ReadOnly); +} + +/** Returns the length of the random source in sectors. + @return length of the source in sectors. +*/ +qint64 CopySourceRandom::length() const +{ + return size() / sectorSize(); +} + +/** Reads the given number of sectors from the random source into the given buffer. + @param buffer buffer to store the sectors read in + @param readOffset offset where to begin reading (unused) + @param numSectors number of sectors to read + @return true on success +*/ +bool CopySourceRandom::readSectors(void* buffer, qint64 readOffset, qint64 numSectors) +{ + Q_UNUSED(readOffset); + + return random().read(static_cast(buffer), numSectors * sectorSize()) == numSectors * sectorSize(); +} diff --git a/src/core/copysourcerandom.h b/src/core/copysourcerandom.h new file mode 100644 index 0000000..d998bf9 --- /dev/null +++ b/src/core/copysourcerandom.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#if !defined(COPYSOURCERANDOM__H) + +#define COPYSOURCERANDOM__H + +#include "core/copysource.h" + +#include + +class CopyTarget; + +/** @brief A source of random data to copy from. + + Represents a random date source to copy from. Used to securely overwrite data on disk. + + @author vl@fidra.de +*/ +class CopySourceRandom : public CopySource +{ + public: + CopySourceRandom(qint64 size, qint32 sectorsize); + + public: + virtual bool open(); + virtual bool readSectors(void* buffer, qint64 readOffset, qint64 numSectors); + virtual qint64 length() const; + + virtual qint32 sectorSize() const { return m_SectorSize; } /**< @return the file's sector size */ + virtual bool overlaps(const CopyTarget&) const { return false; } /**< @return false for random source */ + virtual qint64 firstSector() const { return 0; } /**< @return 0 for random source */ + virtual qint64 lastSector() const { return length(); } /**< @return equal to length for random source. @see length() */ + + protected: + QFile& random() { return m_Random; } + const QFile& random() const { return m_Random; } + qint32 size() const { return m_Size; } + + private: + qint64 m_Size; + qint32 m_SectorSize; + QFile m_Random; +}; + +#endif diff --git a/src/gui/partitionmanagerui.rc b/src/gui/partitionmanagerui.rc index 88ecb70..05ce37d 100644 --- a/src/gui/partitionmanagerui.rc +++ b/src/gui/partitionmanagerui.rc @@ -1,6 +1,6 @@ - + Edit Toolbar @@ -50,6 +50,7 @@ + diff --git a/src/gui/partitionmanagerwidget.cpp b/src/gui/partitionmanagerwidget.cpp index c3b68c0..1033604 100644 --- a/src/gui/partitionmanagerwidget.cpp +++ b/src/gui/partitionmanagerwidget.cpp @@ -215,7 +215,15 @@ void PartitionManagerWidget::setupActions() deletePartition->setToolTip(i18nc("@info:tooltip", "Delete partition")); deletePartition->setStatusTip(i18nc("@info:status", "Delete a partition.")); deletePartition->setShortcut(Qt::Key_Delete); - deletePartition->setIcon(BarIcon("edit-delete-shred")); + deletePartition->setIcon(BarIcon("edit-delete")); + + KAction* shredPartition = actionCollection()->addAction("shredPartition", this, SLOT(onShredPartition())); + shredPartition->setEnabled(false); + shredPartition->setText(i18nc("@action:inmenu", "Shred")); + shredPartition->setToolTip(i18nc("@info:tooltip", "Shred partition")); + shredPartition->setStatusTip(i18nc("@info:status", "Shred a partition so that its contents cannot be restored.")); + shredPartition->setShortcut(Qt::SHIFT | Qt::Key_Delete); + shredPartition->setIcon(BarIcon("edit-delete-shred")); KAction* copyPartition = actionCollection()->addAction("copyPartition", this, SLOT(onCopyPartition())); copyPartition->setEnabled(false); @@ -328,6 +336,7 @@ void PartitionManagerWidget::enableActions() actionCollection()->action("resizePartition")->setEnabled(!readOnly && canResize); actionCollection()->action("copyPartition")->setEnabled(CopyOperation::canCopy(part)); actionCollection()->action("deletePartition")->setEnabled(!readOnly && DeleteOperation::canDelete(part)); + actionCollection()->action("shredPartition")->setEnabled(!readOnly && DeleteOperation::canDelete(part)); actionCollection()->action("pastePartition")->setEnabled(!readOnly && CopyOperation::canPaste(part, clipboardPartition())); actionCollection()->action("propertiesPartition")->setEnabled(part != NULL); @@ -489,6 +498,7 @@ void PartitionManagerWidget::showPartitionContextMenu(const QPoint& pos) partitionMenu.addAction(actionCollection()->action("newPartition")); partitionMenu.addAction(actionCollection()->action("resizePartition")); partitionMenu.addAction(actionCollection()->action("deletePartition")); + partitionMenu.addAction(actionCollection()->action("shredPartition")); partitionMenu.addSeparator(); partitionMenu.addAction(actionCollection()->action("copyPartition")); partitionMenu.addAction(actionCollection()->action("pastePartition")); @@ -664,7 +674,7 @@ void PartitionManagerWidget::onNewPartition() delete dlg; } -void PartitionManagerWidget::onDeletePartition() +void PartitionManagerWidget::onDeletePartition(bool shred) { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); @@ -712,12 +722,17 @@ void PartitionManagerWidget::onDeletePartition() setClipboardPartition(NULL); } - operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition())); + operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition(), shred)); updatePartitions(); emit statusChanged(); emit operationsChanged(); } +void PartitionManagerWidget::onShredPartition() +{ + onDeletePartition(true); +} + void PartitionManagerWidget::onResizePartition() { Q_ASSERT(selectedDevice()); diff --git a/src/gui/partitionmanagerwidget.h b/src/gui/partitionmanagerwidget.h index 5ff8019..5e95762 100644 --- a/src/gui/partitionmanagerwidget.h +++ b/src/gui/partitionmanagerwidget.h @@ -126,7 +126,8 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, void onMountPartition(); void onEditMountPoint(); void onNewPartition(); - void onDeletePartition(); + void onDeletePartition(bool shred = false); + void onShredPartition(); void onResizePartition(); void onCopyPartition(); void onPastePartition(); diff --git a/src/jobs/shredfilesystemjob.cpp b/src/jobs/shredfilesystemjob.cpp new file mode 100644 index 0000000..bff0b6b --- /dev/null +++ b/src/jobs/shredfilesystemjob.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "jobs/shredfilesystemjob.h" + +#include "core/partition.h" +#include "core/device.h" +#include "core/copysourcerandom.h" +#include "core/copytargetdevice.h" + +#include "fs/filesystem.h" +#include "fs/filesystemfactory.h" + +#include "util/report.h" + +#include +#include + +/** Creates a new ShredFileSystemJob + @param d the Device the FileSystem is on + @param p the Partition the FileSystem is in +*/ +ShredFileSystemJob::ShredFileSystemJob(Device& d, Partition& p) : + Job(), + m_Device(d), + m_Partition(p) +{ +} + +qint32 ShredFileSystemJob::numSteps() const +{ + return 100; +} + +bool ShredFileSystemJob::run(Report& parent) +{ + Q_ASSERT(device().deviceNode() == partition().devicePath()); + + if (device().deviceNode() != partition().devicePath()) + { + kWarning() << "deviceNode: " << device().deviceNode() << ", partition path: " << partition().devicePath(); + return false; + } + + bool rval = false; + + Report* report = jobStarted(parent); + + // Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run() + { + CopyTargetDevice copyTarget(device(), partition().fileSystem().firstSector(), partition().fileSystem().lastSector()); + CopySourceRandom copySource(partition().capacity(), copyTarget.sectorSize()); + + if (!copySource.open()) + report->line() << i18nc("@info/plain", "Could not open random data source to overwrite file system."); + else if (!copyTarget.open()) + report->line() << i18nc("@info/plain", "Could not open target partition %1 to restore to.", partition().deviceNode()); + else + { + rval = copyBlocks(*report, copyTarget, copySource); + report->line() << i18nc("@info/plain", "Closing device. This may take a few seconds."); + } + } + + jobFinished(*report, rval); + + return rval; +} + +QString ShredFileSystemJob::description() const +{ + return i18nc("@info/plain", "Shred the file system on %1", partition().deviceNode()); +} diff --git a/src/jobs/shredfilesystemjob.h b/src/jobs/shredfilesystemjob.h new file mode 100644 index 0000000..497b36d --- /dev/null +++ b/src/jobs/shredfilesystemjob.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#if !defined(SHREDFILESYSTEMJOB__H) + +#define SHREDFILESYSTEMJOB__H + +#include "jobs/job.h" + +#include + +class Partition; +class Device; +class Report; + +/** @brief Securely delete and shred a FileSystem. + + Shreds (overwrites with random data) a FileSystem on given Partition and Device. + + @author vl@fidra.de +*/ +class ShredFileSystemJob : public Job +{ + public: + ShredFileSystemJob(Device& d, Partition& p); + + public: + virtual bool run(Report& parent); + virtual qint32 numSteps() const; + virtual QString description() const; + + protected: + Partition& partition() { return m_Partition; } + const Partition& partition() const { return m_Partition; } + + Device& device() { return m_Device; } + const Device& device() const { return m_Device; } + + private: + Device& m_Device; + Partition& m_Partition; +}; + +#endif diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index 95df113..c0a579e 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2008, 2010 by Volker Lanz * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -25,6 +25,7 @@ #include "jobs/deletepartitionjob.h" #include "jobs/deletefilesystemjob.h" +#include "jobs/shredfilesystemjob.h" #include "util/capacity.h" @@ -37,11 +38,14 @@ @param d the Device to delete a Partition on @param p pointer to the Partition to delete. May not be NULL */ -DeleteOperation::DeleteOperation(Device& d, Partition* p) : +DeleteOperation::DeleteOperation(Device& d, Partition* p, bool secure) : Operation(), m_TargetDevice(d), m_DeletedPartition(p), - m_DeleteFileSystemJob(new DeleteFileSystemJob(targetDevice(), deletedPartition())), + m_Secure(secure), + m_DeleteFileSystemJob(isSecure() + ? static_cast(new ShredFileSystemJob(targetDevice(), deletedPartition())) + : static_cast(new DeleteFileSystemJob(targetDevice(), deletedPartition()))), m_DeletePartitionJob(new DeletePartitionJob(targetDevice(), deletedPartition())) { addJob(deleteFileSystemJob()); @@ -68,7 +72,10 @@ void DeleteOperation::undo() QString DeleteOperation::description() const { - return QString(i18nc("@info/plain", "Delete partition %1 (%2, %3)", deletedPartition().deviceNode(), Capacity(deletedPartition()).toString(), deletedPartition().fileSystem().name())); + if (isSecure()) + return QString(i18nc("@info/plain", "Shred partition %1 (%2, %3)", deletedPartition().deviceNode(), Capacity(deletedPartition()).toString(), deletedPartition().fileSystem().name())); + else + return QString(i18nc("@info/plain", "Delete partition %1 (%2, %3)", deletedPartition().deviceNode(), Capacity(deletedPartition()).toString(), deletedPartition().fileSystem().name())); } void DeleteOperation::checkAdjustLogicalNumbers(Partition& p, bool undo) @@ -90,7 +97,7 @@ bool DeleteOperation::canDelete(const Partition* p) { if (p == NULL) return false; - + if (p->isMounted()) return false; diff --git a/src/ops/deleteoperation.h b/src/ops/deleteoperation.h index 5c06d77..c6f74a0 100644 --- a/src/ops/deleteoperation.h +++ b/src/ops/deleteoperation.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2008, 2010 by Volker Lanz * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -29,7 +29,7 @@ class Device; class OperationStack; class Partition; -class DeleteFileSystemJob; +class Job; class DeletePartitionJob; /** @brief Delete a Partition. @@ -43,14 +43,15 @@ class DeleteOperation : public Operation Q_DISABLE_COPY(DeleteOperation) public: - DeleteOperation(Device& d, Partition* p); + DeleteOperation(Device& d, Partition* p, bool secure = false); ~DeleteOperation(); public: - QString iconName() const { return "edit-delete-shred"; } + QString iconName() const { return isSecure() ? "edit-delete-shred" : "edit-delete"; } QString description() const; void preview(); void undo(); + bool isSecure() const { return m_Secure; } static bool canDelete(const Partition* p); @@ -65,13 +66,14 @@ class DeleteOperation : public Operation void setDeletedPartition(Partition* p) { m_DeletedPartition = p; } - DeleteFileSystemJob* deleteFileSystemJob() { return m_DeleteFileSystemJob; } + Job* deleteFileSystemJob() { return m_DeleteFileSystemJob; } DeletePartitionJob* deletePartitionJob() { return m_DeletePartitionJob; } private: Device& m_TargetDevice; Partition* m_DeletedPartition; - DeleteFileSystemJob* m_DeleteFileSystemJob; + bool m_Secure; + Job* m_DeleteFileSystemJob; DeletePartitionJob* m_DeletePartitionJob; };