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
This commit is contained in:
Volker Lanz 2009-08-02 18:47:17 +00:00
parent 079f24cc6d
commit 0e518a5a9d
6 changed files with 69 additions and 4 deletions

View File

@ -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 */ /** @return the minimum capacity valid for this FileSystem in bytes */
qint64 FileSystem::minCapacity() const qint64 FileSystem::minCapacity() const
{ {

View File

@ -93,6 +93,7 @@ class FileSystem
virtual bool check(Report& report, const QString& deviceNode) const; virtual bool check(Report& report, const QString& deviceNode) const;
virtual bool updateUUID(Report& report, const QString& deviceNode) const; virtual bool updateUUID(Report& report, const QString& deviceNode) const;
virtual QString readUUID(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 supportGetUsed() const { return SupportNone; } /**< @return SupportType for getting used capacity */
virtual SupportType supportGetLabel() const { return SupportNone; } /**< @return SupportType for reading label*/ virtual SupportType supportGetLabel() const { return SupportNone; } /**< @return SupportType for reading label*/

View File

@ -21,12 +21,19 @@
#include "util/externalcommand.h" #include "util/externalcommand.h"
#include "util/capacity.h" #include "util/capacity.h"
#include "util/report.h"
#include "util/globallog.h"
#include <klocale.h>
#include <kdebug.h>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QFile>
#include <ctime> #include <ctime>
#include <uuid/uuid.h> #include <uuid/uuid.h>
#include <algorithm>
namespace FS namespace FS
{ {
@ -163,4 +170,40 @@ namespace FS
return cmd.waitFor(-1); 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 <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() << i18nc("@info/plain", "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() << i18nc("@info/plain", "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() << i18nc("@info/plain", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode);
return false;
}
log() << i18nc("@info/plain", "Updated NTFS boot sector for partition <filename>%1</filename> successfully.", deviceNode);
return true;
}
} }

View File

@ -50,6 +50,7 @@ namespace FS
virtual bool resize(Report& report, const QString& deviceNode, qint64 length) const; virtual bool resize(Report& report, const QString& deviceNode, qint64 length) const;
virtual bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel); virtual bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel);
virtual bool updateUUID(Report& report, const QString& deviceNode) const; 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 supportGetUsed() const { return m_GetUsed; }
virtual SupportType supportGetLabel() const { return m_GetLabel; } virtual SupportType supportGetLabel() const { return m_GetLabel; }

View File

@ -92,6 +92,9 @@ bool CopyFileSystemJob::run(Report& parent)
} }
} }
if (rval)
rval = targetPartition().fileSystem().updateBootSector(*report, targetPartition().deviceNode());
jobFinished(*report, rval); jobFinished(*report, rval);
return rval; return rval;

View File

@ -50,7 +50,7 @@ qint32 MoveFileSystemJob::numSteps() const
bool MoveFileSystemJob::run(Report& parent) bool MoveFileSystemJob::run(Report& parent)
{ {
bool rval = false; bool rval = false;
Report* report = jobStarted(parent); Report* report = jobStarted(parent);
// A scope for moveSource and moveTarget, so CopyTargetDevice's dtor runs before we // 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; const qint64 savedLength = partition().fileSystem().length() - 1;
partition().fileSystem().setFirstSector(newStart()); partition().fileSystem().setFirstSector(newStart());
partition().fileSystem().setLastSector(newStart() + savedLength); partition().fileSystem().setLastSector(newStart() + savedLength);
} }
else if (!rollbackCopyBlocks(*report, moveTarget, moveSource)) else if (!rollbackCopyBlocks(*report, moveTarget, moveSource))
report->line() << i18nc("@info/plain", "Rollback for file system on partition <filename>%1</filename> failed.", partition().deviceNode()); report->line() << i18nc("@info/plain", "Rollback for file system on partition <filename>%1</filename> failed.", partition().deviceNode());
report->line() << i18nc("@info/plain", "Closing device. This may take a few seconds."); 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); jobFinished(*report, rval);
return rval; return rval;