/************************************************************************* * Copyright (C) 2008 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * 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 3 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, see .* *************************************************************************/ #include "core/partitionnode.h" #include "core/partition.h" #include "core/partitionrole.h" #include "fs/filesystem.h" /** Tries to find the predecessor for a Partition. @param p the Partition to find a predecessor for @return pointer to the predecessor or nullptr if none was found */ Partition* PartitionNode::predecessor(Partition& p) { Q_ASSERT(p.parent()); Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children(); for (int idx = 1; idx < plist.size(); idx++) if (plist[idx] == &p) return plist[idx - 1]; return nullptr; } /** @overload */ const Partition* PartitionNode::predecessor(const Partition& p) const { Q_ASSERT(p.parent()); const Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children(); for (int idx = 1; idx < plist.size(); idx++) if (plist[idx] == &p) return plist[idx - 1]; return nullptr; } /** Tries to find the successor for a Partition. @param p the Partition to find a successor for @return pointer to the successor or nullptr if none was found */ Partition* PartitionNode::successor(Partition& p) { Q_ASSERT(p.parent()); Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children(); for (int idx = plist.size() - 2; idx >= 0; idx--) if (plist[idx] == &p) return plist[idx + 1]; return nullptr; } /** @overload */ const Partition* PartitionNode::successor(const Partition& p) const { Q_ASSERT(p.parent()); const Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children(); for (int idx = plist.size() - 2; idx >= 0; idx--) if (plist[idx] == &p) return plist[idx + 1]; return nullptr; } /** Inserts a Partition into a PartitionNode's children @param p pointer to the Partition to insert. May be nullptr. @return true on success */ bool PartitionNode::insert(Partition* p) { if (p == nullptr) return false; for (int idx = 0; idx < children().size(); idx++) { if (children()[idx]->firstSector() > p->firstSector()) { children().insert(idx, p); return true; } } children().insert(children().size(), p); return true; } /** Removes a Partition from the PartitionNode's children. @param p pointer to the Partition to remove. May be nullptr. @return true on success. */ bool PartitionNode::remove(Partition* p) { if (p == nullptr) return false; return children().removeOne(p); } /** Deletes all children */ void PartitionNode::clearChildren() { qDeleteAll(children()); children().clear(); } /** Finds a Partition by sector. @param s the sector the Partition is at @param role the PartitionRole the Partition is supposed to have @return pointer to the Partition found or nullptr if none was found */ Partition* PartitionNode::findPartitionBySector(qint64 s, const PartitionRole& role) { const auto partitions = children(); for (auto &p : partitions) { // (women and) children first. ;-) const auto pChildren = p->children(); for (auto &child : pChildren) if ((child->roles().roles() & role.roles()) && s >= child->firstSector() && s <= child->lastSector()) return child; if ((p->roles().roles() & role.roles()) && s >= p->firstSector() && s <= p->lastSector()) return p; } return nullptr; } /** @overload */ const Partition* PartitionNode::findPartitionBySector(qint64 s, const PartitionRole& role) const { for (const auto *p : children()) { for (const auto &child : p->children()) if ((child->roles().roles() & role.roles()) && s >= child->firstSector() && s <= child->lastSector()) return child; if ((p->roles().roles() & role.roles()) && s >= p->firstSector() && s <= p->lastSector()) return p; } return nullptr; } /** Reparents a Partition to this PartitionNode @param p the Partition to reparent */ void PartitionNode::reparent(Partition& p) { p.setParent(this); if (!isRoot()) p.setRoles(PartitionRole(PartitionRole::Logical)); else if (!p.roles().has(PartitionRole::Extended)) p.setRoles(PartitionRole(PartitionRole::Primary)); else p.setRoles(PartitionRole(PartitionRole::Extended)); } /** @return the number of the highest mounted child, e.g. 7 if /dev/sdd7 is a child of this PartitionNode and mounted and /dev/sdd8 and /dev/sdd9 and so on aren't */ qint32 PartitionNode::highestMountedChild() const { qint32 result = -1; for (const auto * p : children()) if (p->number() > result && p->isMounted()) result = p->number(); return result; } /** @return true if any of the partition's children are mounted */ bool PartitionNode::isChildMounted() const { for (const auto * child : children()) if (child->isMounted() || (child->hasChildren() && child->isChildMounted())) return true; return false; }