From 0e518a5a9d656d76ceee6c2cf9d414e7006afba8 Mon Sep 17 00:00:00 2001 From: Volker Lanz Date: Sun, 2 Aug 2009 18:47:17 +0000 Subject: [PATCH] Add a virtual method to the FileSystem base class to allow updating the boot sector for a file system after it has been moved or copied. Currently, only NTFS requires such a special treatment, however. Implement this virtual method for NTFS and update the file system's start sector in the NTFS boot sector according to http://thestarman.pcministry.com/asm/mbr/NTFSBR.htm BUG: 202329 svn path=/trunk/extragear/sysadmin/partitionmanager/; revision=1005978 --- src/fs/filesystem.cpp | 14 +++++++++++ src/fs/filesystem.h | 1 + src/fs/ntfs.cpp | 43 ++++++++++++++++++++++++++++++++++ src/fs/ntfs.h | 1 + src/jobs/copyfilesystemjob.cpp | 3 +++ src/jobs/movefilesystemjob.cpp | 11 +++++---- 6 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 3c7e323..610bdb1 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -185,6 +185,20 @@ QString FileSystem::readUUID(const QString& deviceNode) const } +/** Give implementations of FileSystem a chance to update the boot sector after the + file system has been moved or copied. + @param report Report to write status information to + @param deviceNode the device node for the Partition the FileSystem is on + @return true on success +*/ +bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) const +{ + Q_UNUSED(report); + Q_UNUSED(deviceNode); + + return true; +} + /** @return the minimum capacity valid for this FileSystem in bytes */ qint64 FileSystem::minCapacity() const { diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 8ee87e5..c58dcdd 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -93,6 +93,7 @@ class FileSystem virtual bool check(Report& report, const QString& deviceNode) const; virtual bool updateUUID(Report& report, const QString& deviceNode) const; virtual QString readUUID(const QString& deviceNode) const; + virtual bool updateBootSector(Report& report, const QString& deviceNode) const; virtual SupportType supportGetUsed() const { return SupportNone; } /**< @return SupportType for getting used capacity */ virtual SupportType supportGetLabel() const { return SupportNone; } /**< @return SupportType for reading label*/ diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index dabaa53..08e2528 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -21,12 +21,19 @@ #include "util/externalcommand.h" #include "util/capacity.h" +#include "util/report.h" +#include "util/globallog.h" + +#include +#include #include #include +#include #include #include +#include namespace FS { @@ -163,4 +170,40 @@ namespace FS return cmd.waitFor(-1); } + + bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const + { + report.line() << i18nc("@info/plain", "Updating boot sector for NTFS file system on partition %1.", deviceNode); + + quint32 n = firstSector(); + char* s = reinterpret_cast(&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() << i18nc("@info/plain", "Could not open partition %1 for writing when trying to update the NTFS boot sector.", deviceNode); + return false; + } + + if (!device.seek(0x1c)) + { + log() << i18nc("@info/plain", "Could not seek to position 0x1c on partition %1 when trying to update the NTFS boot sector.", deviceNode); + return false; + } + + if (device.write(s, 4) != 4) + { + log() << i18nc("@info/plain", "Could not write new start sector to partition %1 when trying to update the NTFS boot sector.", deviceNode); + return false; + } + + log() << i18nc("@info/plain", "Updated NTFS boot sector for partition %1 successfully.", deviceNode); + + return true; + } } diff --git a/src/fs/ntfs.h b/src/fs/ntfs.h index 8eed5ea..79e6ce2 100644 --- a/src/fs/ntfs.h +++ b/src/fs/ntfs.h @@ -50,6 +50,7 @@ namespace FS virtual bool resize(Report& report, const QString& deviceNode, qint64 length) const; virtual bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel); virtual bool updateUUID(Report& report, const QString& deviceNode) const; + virtual bool updateBootSector(Report& report, const QString& deviceNode) const; virtual SupportType supportGetUsed() const { return m_GetUsed; } virtual SupportType supportGetLabel() const { return m_GetLabel; } diff --git a/src/jobs/copyfilesystemjob.cpp b/src/jobs/copyfilesystemjob.cpp index 3fab0ba..1483238 100644 --- a/src/jobs/copyfilesystemjob.cpp +++ b/src/jobs/copyfilesystemjob.cpp @@ -92,6 +92,9 @@ bool CopyFileSystemJob::run(Report& parent) } } + if (rval) + rval = targetPartition().fileSystem().updateBootSector(*report, targetPartition().deviceNode()); + jobFinished(*report, rval); return rval; diff --git a/src/jobs/movefilesystemjob.cpp b/src/jobs/movefilesystemjob.cpp index c613a42..d5a3923 100644 --- a/src/jobs/movefilesystemjob.cpp +++ b/src/jobs/movefilesystemjob.cpp @@ -50,7 +50,7 @@ qint32 MoveFileSystemJob::numSteps() const bool MoveFileSystemJob::run(Report& parent) { bool rval = false; - + Report* report = jobStarted(parent); // A scope for moveSource and moveTarget, so CopyTargetDevice's dtor runs before we @@ -73,14 +73,17 @@ bool MoveFileSystemJob::run(Report& parent) const qint64 savedLength = partition().fileSystem().length() - 1; partition().fileSystem().setFirstSector(newStart()); partition().fileSystem().setLastSector(newStart() + savedLength); - } + } else if (!rollbackCopyBlocks(*report, moveTarget, moveSource)) report->line() << i18nc("@info/plain", "Rollback for file system on partition %1 failed.", partition().deviceNode()); - + report->line() << i18nc("@info/plain", "Closing device. This may take a few seconds."); } } - + + if (rval) + rval = partition().fileSystem().updateBootSector(*report, partition().deviceNode()); + jobFinished(*report, rval); return rval;