/*! Scans the device passed in for partitioning systems. If none are found, a partition containing the whole device is created. All created partitions are added to the gPartitions list. */ status_t add_partitions_for(int fd, bool mountFileSystems, bool isBootDevice) { TRACE(("add_partitions_for(fd = %d, mountFS = %s)\n", fd, mountFileSystems ? "yes" : "no")); Partition *partition = new Partition(fd); // set some magic/default values partition->block_size = 512; partition->size = partition->Size(); // add this partition to the list of partitions, if it contains // or might contain a file system if ((partition->Scan(mountFileSystems, isBootDevice) == B_OK && partition->IsFileSystem()) || (!partition->IsPartitioningSystem() && !mountFileSystems)) { gPartitions.Add(partition); return B_OK; } // if not, we no longer need the partition delete partition; return B_OK; }
bool PartitionMap::Check(off_t sessionSize) const { int32 partitionCount = CountPartitions(); // 1. check partition locations for (int32 i = 0; i < partitionCount; i++) { if (!PartitionAt(i)->CheckLocation(sessionSize)) return false; } // 2. check overlapping of partitions and location of partition tables bool result = true; Partition** byOffset = new(nothrow) Partition*[partitionCount]; off_t* tableOffsets = new(nothrow) off_t[partitionCount - 3]; if (byOffset && tableOffsets) { // fill the arrays int32 byOffsetCount = 0; int32 tableOffsetCount = 1; // primary partition table tableOffsets[0] = 0; for (int32 i = 0; i < partitionCount; i++) { Partition* partition = (Partition*)PartitionAt(i); if (!partition->IsExtended()) byOffset[byOffsetCount++] = partition; // add only logical partition partition table locations if (i >= 4) { tableOffsets[tableOffsetCount++] = partition->PartitionTableOffset(); } } // sort the arrays qsort(byOffset, byOffsetCount, sizeof(Partition*), cmp_partition_offset); qsort(tableOffsets, tableOffsetCount, sizeof(off_t), cmp_offset); // check for overlappings off_t nextOffset = 0; for (int32 i = 0; i < byOffsetCount; i++) { Partition* partition = byOffset[i]; if (partition->Offset() < nextOffset && i > 0) { Partition* previousPartition = byOffset[i - 1]; off_t previousSize = previousPartition->Size() - (nextOffset - partition->Offset()); TRACE(("intel: PartitionMap::Check(): ")); if (previousSize == 0) { previousPartition->Unset(); TRACE(("partition offset hides previous partition." " Removing previous partition from disk layout.\n")); } else { TRACE(("overlapping partitions! Setting partition %ld " "size to %lld\n", i - 1, previousSize)); previousPartition->SetSize(previousSize); } } nextOffset = partition->Offset() + partition->Size(); } // check uniqueness of partition table offsets and whether they lie // outside of the non-extended partitions if (result) { for (int32 i = 0; i < tableOffsetCount; i++) { if (i > 0 && tableOffsets[i] == tableOffsets[i - 1]) { TRACE(("intel: PartitionMap::Check(): same partition table " "for different extended partitions!\n")); result = false; break; } else if (is_inside_partitions(tableOffsets[i], (const Partition**)byOffset, byOffsetCount)) { TRACE(("intel: PartitionMap::Check(): a partition table " "lies inside a non-extended partition!\n")); result = false; break; } } } } else result = false; // no memory: assume failure // cleanup delete[] byOffset; delete[] tableOffsets; return result; }