File indexing completed on 2024-04-28 05:45:46

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
0003     SPDX-FileCopyrightText: 2014-2016 Andrius Štikonas <andrius@stikonas.eu>
0004     SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-3.0-or-later
0007 */
0008 
0009 #include "core/partitionnode.h"
0010 
0011 #include "core/partition.h"
0012 #include "core/partitionrole.h"
0013 
0014 #include "fs/filesystem.h"
0015 
0016 /** Tries to find the predecessor for a Partition.
0017     @param p the Partition to find a predecessor for
0018     @return pointer to the predecessor or nullptr if none was found
0019 */
0020 Partition* PartitionNode::predecessor(Partition& p)
0021 {
0022     Q_ASSERT(p.parent());
0023 
0024     Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children();
0025 
0026     for (int idx = 1; idx < plist.size(); idx++)
0027         if (plist[idx] == &p)
0028             return plist[idx - 1];
0029 
0030     return nullptr;
0031 }
0032 
0033 /**
0034     @overload
0035 */
0036 const Partition* PartitionNode::predecessor(const Partition& p) const
0037 {
0038     Q_ASSERT(p.parent());
0039 
0040     const Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children();
0041 
0042     for (int idx = 1; idx < plist.size(); idx++)
0043         if (plist[idx] == &p)
0044             return plist[idx - 1];
0045 
0046     return nullptr;
0047 }
0048 
0049 /** Tries to find the successor for a Partition.
0050     @param p the Partition to find a successor for
0051     @return pointer to the successor or nullptr if none was found
0052  */
0053 Partition* PartitionNode::successor(Partition& p)
0054 {
0055     Q_ASSERT(p.parent());
0056 
0057     Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children();
0058 
0059     for (int idx = plist.size() - 2; idx >= 0; idx--)
0060         if (plist[idx] == &p)
0061             return plist[idx + 1];
0062 
0063     return nullptr;
0064 }
0065 
0066 /**
0067     @overload
0068 */
0069 const Partition* PartitionNode::successor(const Partition& p) const
0070 {
0071     Q_ASSERT(p.parent());
0072 
0073     const Partitions& plist = p.parent()->isRoot() == false ? p.parent()->children() : children();
0074 
0075     for (int idx = plist.size() - 2; idx >= 0; idx--)
0076         if (plist[idx] == &p)
0077             return plist[idx + 1];
0078 
0079     return nullptr;
0080 }
0081 
0082 /** Inserts a Partition into a PartitionNode's children
0083     @param p pointer to the Partition to insert. May be nullptr.
0084     @return true on success
0085 */
0086 bool PartitionNode::insert(Partition* p)
0087 {
0088     if (p == nullptr)
0089         return false;
0090 
0091     for (int idx = 0; idx < children().size(); idx++) {
0092         if (children()[idx]->firstSector() > p->firstSector()) {
0093             children().insert(idx, p);
0094             return true;
0095         }
0096     }
0097 
0098     children().insert(children().size(), p);
0099 
0100     return true;
0101 }
0102 
0103 /** Removes a Partition from the PartitionNode's children.
0104     @param p pointer to the Partition to remove. May be nullptr.
0105     @return true on success.
0106 */
0107 bool PartitionNode::remove(Partition* p)
0108 {
0109     if (p == nullptr)
0110         return false;
0111 
0112     return children().removeOne(p);
0113 }
0114 
0115 /** Deletes all children */
0116 void PartitionNode::clearChildren()
0117 {
0118     qDeleteAll(children());
0119     children().clear();
0120 }
0121 
0122 /** Finds a Partition by sector.
0123     @param s the sector the Partition is at
0124     @param role the PartitionRole the Partition is supposed to have
0125     @return pointer to the Partition found or nullptr if none was found
0126 */
0127 Partition* PartitionNode::findPartitionBySector(qint64 s, const PartitionRole& role)
0128 {
0129     const auto partitions = children();
0130     for (auto &p : partitions) {
0131         // (women and) children first. ;-)
0132         const auto pChildren = p->children();
0133         for (auto &child : pChildren)
0134             if ((child->roles().roles() & role.roles()) && s >= child->firstSector() && s <= child->lastSector())
0135                 return child;
0136 
0137         if ((p->roles().roles() & role.roles()) && s >= p->firstSector() && s <= p->lastSector())
0138             return p;
0139     }
0140 
0141     return nullptr;
0142 }
0143 
0144 /**
0145     @overload
0146 */
0147 const Partition* PartitionNode::findPartitionBySector(qint64 s, const PartitionRole& role) const
0148 {
0149     for (const auto *p : children()) {
0150         for (const auto &child : p->children())
0151             if ((child->roles().roles() & role.roles()) && s >= child->firstSector() && s <= child->lastSector())
0152                 return child;
0153 
0154         if ((p->roles().roles() & role.roles()) && s >= p->firstSector() && s <= p->lastSector())
0155             return p;
0156     }
0157 
0158     return nullptr;
0159 }
0160 
0161 /** Reparents a Partition to this PartitionNode
0162     @param p the Partition to reparent
0163 */
0164 void PartitionNode::reparent(Partition& p)
0165 {
0166     p.setParent(this);
0167 
0168     if (!isRoot())
0169         p.setRoles(PartitionRole(PartitionRole::Logical));
0170     else if (!p.roles().has(PartitionRole::Extended))
0171         p.setRoles(PartitionRole(PartitionRole::Primary));
0172     else
0173         p.setRoles(PartitionRole(PartitionRole::Extended));
0174 }
0175 
0176 /** @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
0177 */
0178 qint32 PartitionNode::highestMountedChild() const
0179 {
0180     qint32 result = -1;
0181 
0182     for (const auto * p : children())
0183         if (p->number() > result && p->isMounted())
0184             result = p->number();
0185 
0186     return result;
0187 }
0188 
0189 /** @return true if any of the partition's children are mounted */
0190 bool PartitionNode::isChildMounted() const
0191 {
0192     for (const auto * child : children())
0193         if (child->isMounted() || (child->hasChildren() && child->isChildMounted()))
0194             return true;
0195 
0196     return false;
0197 }