Logo Search packages:      
Sourcecode: partitionmanager version File versions  Download package

restoreoperation.cpp

/***************************************************************************
 *   Copyright (C) 2008 by Volker Lanz <vl@fidra.de>                       *
 *                                                                         *
 *   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 "ops/restoreoperation.h"

#include "core/partition.h"
#include "core/device.h"
#include "core/partitiontable.h"
#include "core/partitionnode.h"

#include "jobs/createpartitionjob.h"
#include "jobs/deletepartitionjob.h"
#include "jobs/checkfilesystemjob.h"
#include "jobs/restorefilesystemjob.h"
#include "jobs/resizefilesystemjob.h"

#include "fs/filesystem.h"
#include "fs/filesystemfactory.h"

#include "util/capacity.h"
#include "util/report.h"

#include <QString>
#include <QFileInfo>

#include <kdebug.h>
#include <klocale.h>

/** Creates a new RestoreOperation.
      @param d the Device to restore the Partition to
      @param p pointer to the Partition that will be restored. May not be NULL.
      @param filename name of the image file to restore from
*/
00050 RestoreOperation::RestoreOperation(Device& d, Partition* p, const QString& filename) :
      Operation(),
      m_TargetDevice(d),
      m_RestorePartition(p),
      m_FileName(filename),
      m_OverwrittenPartition(NULL),
      m_MustDeleteOverwritten(false),
      m_ImageLength(QFileInfo(filename).size() / 512), // 512 being the "sector size" of an image file.
      m_CreatePartitionJob(NULL),
      m_RestoreJob(NULL),
      m_CheckTargetJob(NULL),
      m_MaximizeJob(NULL)
{
      restorePartition().setState(Partition::StateRestore);

      Q_ASSERT(targetDevice().partitionTable());

      Partition* dest = targetDevice().partitionTable()->findPartitionBySector(restorePartition().firstSector(), PartitionRole(PartitionRole::Primary | PartitionRole::Logical | PartitionRole::Unallocated));

      Q_ASSERT(dest);

      if (dest == NULL)
            kWarning() << "destination partition not found at sector " << restorePartition().firstSector();

      if (dest && !dest->roles().has(PartitionRole::Unallocated))
      {
            restorePartition().setLastSector(dest->lastSector());
            setOverwrittenPartition(dest);
            removePreviewPartition(targetDevice(), *dest);
      }

      if (!overwrittenPartition())
            addJob(m_CreatePartitionJob = new CreatePartitionJob(targetDevice(), restorePartition()));

      addJob(m_RestoreJob = new RestoreFileSystemJob(targetDevice(), restorePartition(), fileName()));
      addJob(m_CheckTargetJob = new CheckFileSystemJob(restorePartition()));
      addJob(m_MaximizeJob = new ResizeFileSystemJob(targetDevice(), restorePartition()));
}

RestoreOperation::~RestoreOperation()
{
      if (status() == StatusPending)
            delete m_RestorePartition;

      if (status() == StatusFinishedSuccess || status() == StatusFinishedWarning || status() == StatusError)
            cleanupOverwrittenPartition();
}

00098 void RestoreOperation::preview()
{
      insertPreviewPartition(targetDevice(), restorePartition());
}

00103 void RestoreOperation::undo()
{
      removePreviewPartition(targetDevice(), restorePartition());

      if (overwrittenPartition())
            insertPreviewPartition(targetDevice(), *overwrittenPartition());
}

00111 bool RestoreOperation::execute(Report& parent)
{
      bool rval = false;
      bool warning = false;

      Report* report = parent.newChild(description());

      if (overwrittenPartition())
            restorePartition().setNumber(overwrittenPartition()->number());

      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() << i18nc("@info/plain", "Warning: Maximizing file system on target partition <filename>%1</filename> to the size of the partition failed.", restorePartition().deviceNode());
                  }
                  else
                        report->line() << i18nc("@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;
}

00160 QString RestoreOperation::description() const
{
      if (overwrittenPartition())
            return QString(i18nc("@info/plain", "Restore partition from <filename>%1</filename> to <filename>%2</filename>", fileName(), overwrittenPartition()->deviceNode()));

      return QString(i18nc("@info/plain", "Restore partition on <filename>%1</filename> at %2 from <filename>%3</filename>", targetDevice().deviceNode(), Capacity(restorePartition().firstSector() * restorePartition().sectorSize()).toString(), fileName()));
}

void RestoreOperation::setOverwrittenPartition(Partition* p)
{
      // This is copied from CopyOperation. One day we might create a common base class ;-)

      cleanupOverwrittenPartition();
      m_OverwrittenPartition = p;
      m_MustDeleteOverwritten = (p && p->state() == Partition::StateNone);
}

void RestoreOperation::cleanupOverwrittenPartition()
{
      if (mustDeleteOverwritten())
      {
            delete overwrittenPartition();
            m_OverwrittenPartition = NULL;
      }
}

/** Can a Partition be restored to somewhere?
      @param p the Partition in question, may be NULL.
      @return true if a Partition can be restored to @p p.
 */
00190 bool RestoreOperation::canRestore(const Partition* p)
{
      if (p == NULL)
            return false;

      if (p->isMounted())
            return false;

      if (p->roles().has(PartitionRole::Extended))
            return false;

      return true;
}
/** Creates a new Partition to restore to.
      @param device the Device to create the Partition on
      @param parent the parent PartitionNode
      @param start start sector of the Partition
      @param filename name of the image file to restore from
*/
00209 Partition* RestoreOperation::createRestorePartition(const Device& device, PartitionNode& parent, qint64 start, const QString& filename)
{
      PartitionRole::Roles r = PartitionRole::Primary;

      if (!parent.isRoot())
            r = PartitionRole::Logical;

      QFileInfo fileInfo(filename);

      if (!fileInfo.exists())
            return NULL;

      const qint64 end = start + fileInfo.size() / device.sectorSize() - 1;
      Partition* p = new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Unknown, start, end), start, end, -1);

      p->setState(Partition::StateRestore);
      return p;
}


Generated by  Doxygen 1.6.0   Back to index