private int GetPartitionOffset(int index)
        {
            bool found        = false;
            int  entriesSoFar = 0;
            int  position     = 0;

            while (!found && position < _primaryHeader.PartitionEntryCount)
            {
                GptEntry entry = new GptEntry();
                entry.ReadFrom(_entryBuffer, position * _primaryHeader.PartitionEntrySize);
                if (entry.PartitionType != Guid.Empty)
                {
                    if (index == entriesSoFar)
                    {
                        found = true;
                        break;
                    }

                    entriesSoFar++;
                }

                position++;
            }

            if (found)
            {
                return(position * _primaryHeader.PartitionEntrySize);
            }
            else
            {
                throw new IOException(string.Format(CultureInfo.InvariantCulture, "No such partition: {0}", index));
            }
        }
        private void EstablishReservedPartition(List <GptEntry> allEntries)
        {
            // If no MicrosoftReserved partition, and no Microsoft Data partitions, and the disk
            // has a 'reasonable' size free, create a Microsoft Reserved partition.
            if (CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.MicrosoftReserved) == 0 &&
                CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.WindowsBasicData) == 0 &&
                _diskGeometry.Capacity > 512 * 1024 * 1024)
            {
                long reservedStart = FirstAvailableSector(allEntries);
                long reservedEnd   = FindLastFreeSector(reservedStart, allEntries);

                if ((reservedEnd - reservedStart + 1) * _diskGeometry.BytesPerSector > 512 * 1024 * 1024)
                {
                    long size = ((_diskGeometry.Capacity < (16 * 1024L * 1024 * 1024)) ? 32 : 128) * 1024 * 1024;
                    reservedEnd = reservedStart + (size / _diskGeometry.BytesPerSector) - 1;

                    int      reservedOffset   = GetFreeEntryOffset();
                    GptEntry newReservedEntry = new GptEntry();
                    newReservedEntry.PartitionType         = GuidPartitionTypes.MicrosoftReserved;
                    newReservedEntry.Identity              = Guid.NewGuid();
                    newReservedEntry.FirstUsedLogicalBlock = reservedStart;
                    newReservedEntry.LastUsedLogicalBlock  = reservedEnd;
                    newReservedEntry.Attributes            = 0;
                    newReservedEntry.Name = "Microsoft reserved partition";
                    newReservedEntry.WriteTo(_entryBuffer, reservedOffset);
                    allEntries.Add(newReservedEntry);
                }
            }
        }
        internal SparseStream Open(GptEntry entry)
        {
            long start = entry.FirstUsedLogicalBlock * _diskGeometry.BytesPerSector;
            long end   = (entry.LastUsedLogicalBlock + 1) * _diskGeometry.BytesPerSector;

            return(new SubStream(_diskData, start, end - start));
        }
 private IEnumerable <GptEntry> GetAllEntries()
 {
     for (int i = 0; i < _primaryHeader.PartitionEntryCount; ++i)
     {
         GptEntry entry = new GptEntry();
         entry.ReadFrom(_entryBuffer, i * _primaryHeader.PartitionEntrySize);
         if (entry.PartitionType != Guid.Empty)
         {
             yield return(entry);
         }
     }
 }
        private int GetFreeEntryOffset()
        {
            for (int i = 0; i < _primaryHeader.PartitionEntryCount; ++i)
            {
                GptEntry entry = new GptEntry();
                entry.ReadFrom(_entryBuffer, i * _primaryHeader.PartitionEntrySize);

                if (entry.PartitionType == Guid.Empty)
                {
                    return(i * _primaryHeader.PartitionEntrySize);
                }
            }

            throw new IOException("No free partition entries available");
        }
        private int GetEntryIndex(Guid identity)
        {
            int index = 0;

            for (int i = 0; i < _primaryHeader.PartitionEntryCount; ++i)
            {
                GptEntry entry = new GptEntry();
                entry.ReadFrom(_entryBuffer, i * _primaryHeader.PartitionEntrySize);

                if (entry.Identity == identity)
                {
                    return(index);
                }
                else if (entry.PartitionType != Guid.Empty)
                {
                    index++;
                }
            }

            throw new IOException("No such partition");
        }
        private GptEntry CreateEntry(long startSector, long endSector, Guid type, long attributes, string name)
        {
            if (endSector < startSector)
            {
                throw new ArgumentException("The end sector is before the start sector");
            }

            int      offset   = GetFreeEntryOffset();
            GptEntry newEntry = new GptEntry();

            newEntry.PartitionType         = type;
            newEntry.Identity              = Guid.NewGuid();
            newEntry.FirstUsedLogicalBlock = startSector;
            newEntry.LastUsedLogicalBlock  = endSector;
            newEntry.Attributes            = (ulong)attributes;
            newEntry.Name = name;
            newEntry.WriteTo(_entryBuffer, offset);

            // Commit changes to disk
            Write();

            return(newEntry);
        }
Beispiel #8
0
 internal GuidPartitionInfo(GuidPartitionTable table, GptEntry entry)
 {
     _table = table;
     _entry = entry;
 }
        /// <summary>
        /// Creates a new GUID partition on the disk.
        /// </summary>
        /// <param name="startSector">The first sector of the partition.</param>
        /// <param name="endSector">The last sector of the partition.</param>
        /// <param name="type">The partition type.</param>
        /// <param name="attributes">The partition attributes.</param>
        /// <param name="name">The name of the partition.</param>
        /// <returns>The index of the new partition.</returns>
        /// <remarks>No checking is performed on the parameters, the caller is
        /// responsible for ensuring that the partition does not overlap other partitions.</remarks>
        public int Create(long startSector, long endSector, Guid type, long attributes, string name)
        {
            GptEntry newEntry = CreateEntry(startSector, endSector, type, attributes, name);

            return(GetEntryIndex(newEntry.Identity));
        }