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

setpartflagsjob.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 "jobs/setpartflagsjob.h"

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

#include "util/report.h"

#include <klocale.h>

static const struct
{
      PedPartitionFlag pedFlag;
      PartitionTable::Flag flag;
} flagmap[] =
{
      { PED_PARTITION_BOOT, PartitionTable::FlagBoot },
      { PED_PARTITION_ROOT, PartitionTable::FlagRoot },
      { PED_PARTITION_SWAP, PartitionTable::FlagSwap },
      { PED_PARTITION_HIDDEN, PartitionTable::FlagHidden },
      { PED_PARTITION_RAID, PartitionTable::FlagRaid },
      { PED_PARTITION_LVM, PartitionTable::FlagLvm },
      { PED_PARTITION_LBA, PartitionTable::FlagLba },
      { PED_PARTITION_HPSERVICE, PartitionTable::FlagHpService },
      { PED_PARTITION_PALO, PartitionTable::FlagPalo },
      { PED_PARTITION_PREP, PartitionTable::FlagPrep },
      { PED_PARTITION_MSFT_RESERVED, PartitionTable::FlagMsftReserved }
};

/** Creates a new SetPartFlagsJob
      @param d the Device the Partition whose flags are to be set is on
      @param p the Partition whose flags are to be set
      @param flags the new flags for the Partition
*/
00055 SetPartFlagsJob::SetPartFlagsJob(Device& d, Partition& p, PartitionTable::Flags flags) :
      Job(),
      m_Device(d),
      m_Partition(p),
      m_Flags(flags)
{
}

00063 qint32 SetPartFlagsJob::numSteps() const
{
      return sizeof(flagmap) / sizeof(flagmap[0]);
}

00068 bool SetPartFlagsJob::run(Report& parent)
{
      bool rval = true;

      Report* report = jobStarted(parent);
      
      if (openPed(device().deviceNode()))
      {
            PedPartition* pedPartition = (partition().roles().has(PartitionRole::Extended)) ? ped_disk_extended_partition(pedDisk()) : ped_disk_get_partition_by_sector(pedDisk(), partition().firstSector());

            if (pedPartition)
            {
                  for (quint32 i = 0; i < sizeof(flagmap) / sizeof(flagmap[0]); i++)
                  {
                        emit progress(i + 1);

                        if (!ped_partition_is_flag_available(pedPartition, flagmap[i].pedFlag))
                        {
                              report->line() << i18nc("@info/plain", "The flag \"%1\" is not available on the partition's partition table.", PartitionTable::flagName(flagmap[i].flag));
                              continue;
                        }

                        // Workaround: libparted claims the hidden flag is available for extended partitions, but
                        // throws an error when we try to set or clear it. So skip this combination (also see below in
                        // availableFlags()).
                        if (pedPartition->type == PED_PARTITION_EXTENDED && flagmap[i].flag == PartitionTable::FlagHidden)
                              continue;

                        int state = (flags() & flagmap[i].flag) ? 1 : 0;

                        if (!ped_partition_set_flag(pedPartition, flagmap[i].pedFlag, state))
                        {
                              report->line() << i18nc("@info/plain", "There was an error setting flag %1 for partition <filename>%2</filename> to state %3.", PartitionTable::flagName(flagmap[i].flag), partition().deviceNode(), state ? i18nc("@info flag turned on, active", "on") : i18nc("@info flag turned off, inactive", "off"));

                              rval = false;
                        }
                  }
      
                  if (!commit())
                        rval = false;
            }
            else
                  report->line() << i18nc("@info/plain", "Could not find partition <filename>%1</filename> on device <filename>%2</filename> to set partition flags.", partition().deviceNode(), device().deviceNode());
      
            closePed();
      }
      else
            report->line() << i18nc("@info/plain", "Could not open device <filename>%1</filename> to set partition flags for partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
      
      if (rval)
            partition().setFlags(flags());

      jobFinished(*report, rval);

      return rval;
}

PartitionTable::Flags SetPartFlagsJob::activeFlags(PedPartition* p)
{
      PartitionTable::Flags flags = PartitionTable::FlagNone;

      // We might get here with a pedPartition just picked up from libparted that is
      // unallocated. Libparted doesn't like it if we ask for flags for unallocated
      // space.
      if (p->num <= 0)
            return flags;
      
      for (quint32 i = 0; i < sizeof(flagmap) / sizeof(flagmap[0]); i++)
            if (ped_partition_is_flag_available(p, flagmap[i].pedFlag) && ped_partition_get_flag(p, flagmap[i].pedFlag))
                  flags |= flagmap[i].flag;

      return flags;
}

PartitionTable::Flags SetPartFlagsJob::availableFlags(PedPartition* p)
{
      PartitionTable::Flags flags;
      
      // see above.
      if (p->num <= 0)
            return flags;
      
      for (quint32 i = 0; i < sizeof(flagmap) / sizeof(flagmap[0]); i++)
            if (ped_partition_is_flag_available(p, flagmap[i].pedFlag))
            {
                  // workaround:: see above
                  if (p->type != PED_PARTITION_EXTENDED || flagmap[i].flag != PartitionTable::FlagHidden)
                        flags |= flagmap[i].flag;
            }
      
      return flags;
}

00161 QString SetPartFlagsJob::description() const
{
      if (PartitionTable::flagNames(flags()).size() == 0)
            return QString(i18nc("@info/plain", "Clear flags for partition <filename>%1</filename>", partition().deviceNode()));

      return i18nc("@info/plain", "Set the flags for partition <filename>%1</filename> to \"%2\"", partition().deviceNode(), PartitionTable::flagNames(flags()).join(","));
}

Generated by  Doxygen 1.6.0   Back to index