Add end-alignment feature.
This commit is contained in:
		
							
								
								
									
										10
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,9 +1,17 @@
 | 
			
		||||
1.0.9 (?/?/2021):
 | 
			
		||||
1.0.9 (?/?/2022):
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
- Removed stray debugging code that caused "partNum is {x}" to be printed
 | 
			
		||||
  when changing a partition's name with sgdisk (-c/--change-name).
 | 
			
		||||
 | 
			
		||||
- Added support for aligning partitions' end points, as well as their start
 | 
			
		||||
  points. This support affects the default partition size when using 'n' in
 | 
			
		||||
  gdisk; it affects the default partition size in cgdisk; and it's activated
 | 
			
		||||
  by the new '-I' option in sgdisk. See the programs' respective man pages
 | 
			
		||||
  for details. This feature is intended to help with LUKS2 encryption, which
 | 
			
		||||
  reacts badly to partitions that are not sized as exact multiples of the
 | 
			
		||||
  encryption block size.
 | 
			
		||||
 | 
			
		||||
1.0.8 (6/9/2021):
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								cgdisk.8
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								cgdisk.8
									
									
									
									
									
								
							@@ -186,8 +186,13 @@ new disks, GPT fdisk attempts to align partitions on 1 MiB boundaries
 | 
			
		||||
performance for all of these disk types. On pre\-partitioned disks, GPT
 | 
			
		||||
fdisk attempts to identify the alignment value used on that disk, but will
 | 
			
		||||
set 8-sector alignment on disks larger than 300 GB even if lesser alignment
 | 
			
		||||
values are detected. In either case, it can be changed by using this
 | 
			
		||||
option.
 | 
			
		||||
values are detected. In either case, it can be changed by using this option.
 | 
			
		||||
The alignment value also affects the default end sector value when creating
 | 
			
		||||
a new partition; it will be aligned to one less than a multiple of the
 | 
			
		||||
alignment value, when possible. This should keep partitions a multiple of
 | 
			
		||||
the alignment value in size. Some disk encryption tools require partitions
 | 
			
		||||
to be sized to some value, typically 4096 bytes, so the default alignment of
 | 
			
		||||
1 MiB works well for them.
 | 
			
		||||
 | 
			
		||||
.TP 
 | 
			
		||||
.B Backup
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								gdisk.8
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								gdisk.8
									
									
									
									
									
								
							@@ -210,7 +210,8 @@ default start sector, or \fI\fB\-200M\fR\fR to specify a point 200MiB
 | 
			
		||||
before the last available sector. Pressing the Enter key with no input
 | 
			
		||||
specifies the default value, which is the start of the largest available
 | 
			
		||||
block for the start sector and the end of the same block for the end
 | 
			
		||||
sector.
 | 
			
		||||
sector. Default start and end points may be adjusted to optimize partition
 | 
			
		||||
alignment.
 | 
			
		||||
 | 
			
		||||
.TP 
 | 
			
		||||
.B o
 | 
			
		||||
@@ -491,13 +492,18 @@ Change the sector alignment value. Disks with more logical sectors per
 | 
			
		||||
physical sectors (such as modern Advanced Format drives), some RAID
 | 
			
		||||
configurations, and many SSD devices, can suffer performance problems if
 | 
			
		||||
partitions are not aligned properly for their internal data structures. On
 | 
			
		||||
new disks, GPT fdisk attempts to align partitions on 1 MiB boundaries
 | 
			
		||||
(2048\-sectors on disks with 512-byte sectors) by default, which optimizes
 | 
			
		||||
new disks, GPT fdisk attempts to align partitions on 1 MiB boundaries (2048
 | 
			
		||||
sectors on disks with 512-byte sectors) by default, which optimizes
 | 
			
		||||
performance for all of these disk types. On pre\-partitioned disks, GPT
 | 
			
		||||
fdisk attempts to identify the alignment value used on that disk, but will
 | 
			
		||||
set 8-sector alignment on disks larger than 300 GB even if lesser alignment
 | 
			
		||||
values are detected. In either case, it can be changed by using this
 | 
			
		||||
option.
 | 
			
		||||
values are detected. In either case, it can be changed by using this option.
 | 
			
		||||
The alignment value also affects the default end sector value when creating
 | 
			
		||||
a new partition; it will be aligned to one less than a multiple of the
 | 
			
		||||
alignment value, if possible. This should keep partitions a multiple of the
 | 
			
		||||
alignment value in size. Some disk encryption tools require partitions to be
 | 
			
		||||
sized to some value, typically 4096 bytes, so the default alignment of 1 MiB
 | 
			
		||||
works well for them.
 | 
			
		||||
 | 
			
		||||
.TP 
 | 
			
		||||
.B m
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								gpt.cc
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								gpt.cc
									
									
									
									
									
								
							@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
/* By Rod Smith, initial coding January to February, 2009 */
 | 
			
		||||
 | 
			
		||||
/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
 | 
			
		||||
/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
 | 
			
		||||
  under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 | 
			
		||||
 | 
			
		||||
#define __STDC_LIMIT_MACROS
 | 
			
		||||
@@ -410,6 +410,11 @@ int GPTData::Verify(void) {
 | 
			
		||||
              << "in degraded performance on some modern (2009 and later) hard disks.\n";
 | 
			
		||||
         alignProbs++;
 | 
			
		||||
      } // if
 | 
			
		||||
      if ((partitions[i].IsUsed()) && ((partitions[i].GetLastLBA() + 1) % testAlignment) != 0) {
 | 
			
		||||
         cout << "\nCaution: Partition " << i + 1 << " doesn't end on a "
 | 
			
		||||
              << testAlignment << "-sector boundary. This may\nresult "
 | 
			
		||||
              << "in problems with some disk encryption tools.\n";
 | 
			
		||||
      } // if
 | 
			
		||||
   } // for
 | 
			
		||||
   if (alignProbs > 0)
 | 
			
		||||
      cout << "\nConsult http://www.ibm.com/developerworks/linux/library/l-4kb-sector-disks/\n"
 | 
			
		||||
@@ -2334,18 +2339,28 @@ uint64_t GPTData::FindLastAvailable(void) {
 | 
			
		||||
} // GPTData::FindLastAvailable()
 | 
			
		||||
 | 
			
		||||
// Find the last available block in the free space pointed to by start.
 | 
			
		||||
uint64_t GPTData::FindLastInFree(uint64_t start) {
 | 
			
		||||
   uint64_t nearestStart;
 | 
			
		||||
// If align == true, returns the last sector that's aligned on the
 | 
			
		||||
// system alignment value (unless that's less than the start value);
 | 
			
		||||
// if align == false, returns the last available block regardless of
 | 
			
		||||
// alignment. (The align variable is set to false by default.)
 | 
			
		||||
uint64_t GPTData::FindLastInFree(uint64_t start, bool align) {
 | 
			
		||||
   uint64_t nearestEnd, endPlus;
 | 
			
		||||
   uint32_t i;
 | 
			
		||||
 | 
			
		||||
   nearestStart = mainHeader.lastUsableLBA;
 | 
			
		||||
   nearestEnd = mainHeader.lastUsableLBA;
 | 
			
		||||
   for (i = 0; i < numParts; i++) {
 | 
			
		||||
      if ((nearestStart > partitions[i].GetFirstLBA()) &&
 | 
			
		||||
      if ((nearestEnd > partitions[i].GetFirstLBA()) &&
 | 
			
		||||
          (partitions[i].GetFirstLBA() > start)) {
 | 
			
		||||
         nearestStart = partitions[i].GetFirstLBA() - 1;
 | 
			
		||||
         nearestEnd = partitions[i].GetFirstLBA() - 1;
 | 
			
		||||
      } // if
 | 
			
		||||
   } // for
 | 
			
		||||
   return (nearestStart);
 | 
			
		||||
   if (align) {
 | 
			
		||||
       endPlus = nearestEnd + 1;
 | 
			
		||||
       if (Align(&endPlus) && IsFree(endPlus - 1) && (endPlus > start)) {
 | 
			
		||||
           nearestEnd = endPlus - 1;
 | 
			
		||||
       } // if
 | 
			
		||||
   } // if
 | 
			
		||||
   return (nearestEnd);
 | 
			
		||||
} // GPTData::FindLastInFree()
 | 
			
		||||
 | 
			
		||||
// Finds the total number of free blocks, the number of segments in which
 | 
			
		||||
@@ -2422,7 +2437,10 @@ int GPTData::IsUsedPartNum(uint32_t partNum) {
 | 
			
		||||
 ***********************************************************/
 | 
			
		||||
 | 
			
		||||
// Set partition alignment value; partitions will begin on multiples of
 | 
			
		||||
// the specified value
 | 
			
		||||
// the specified value, and the default end values will be set so that
 | 
			
		||||
// partition sizes are multiples of this value in cgdisk and gdisk, too.
 | 
			
		||||
// (In sgdisk, end-alignment is done only if the '-I' command-line option
 | 
			
		||||
// is used.)
 | 
			
		||||
void GPTData::SetAlignment(uint32_t n) {
 | 
			
		||||
   if (n > 0) {
 | 
			
		||||
      sectorAlignment = n;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								gpt.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								gpt.h
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
/* gpt.h -- GPT and data structure definitions, types, and
 | 
			
		||||
   functions */
 | 
			
		||||
 | 
			
		||||
/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
 | 
			
		||||
/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
 | 
			
		||||
  under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 | 
			
		||||
 | 
			
		||||
#ifndef __GPTSTRUCTS
 | 
			
		||||
@@ -185,7 +185,7 @@ public:
 | 
			
		||||
   uint64_t FindFirstUsedLBA(void);
 | 
			
		||||
   uint64_t FindFirstInLargest(void);
 | 
			
		||||
   uint64_t FindLastAvailable();
 | 
			
		||||
   uint64_t FindLastInFree(uint64_t start);
 | 
			
		||||
   uint64_t FindLastInFree(uint64_t start, bool align = false);
 | 
			
		||||
   uint64_t FindFreeBlocks(uint32_t *numSegments, uint64_t *largestSegment);
 | 
			
		||||
   int IsFree(uint64_t sector, uint32_t *partNum = NULL);
 | 
			
		||||
   int IsFreePartNum(uint32_t partNum);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								gptcl.cc
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								gptcl.cc
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
    Implementation of GPTData class derivative with popt-based command
 | 
			
		||||
    line processing
 | 
			
		||||
    Copyright (C) 2010-2014 Roderick W. Smith
 | 
			
		||||
    Copyright (C) 2010-2022 Roderick W. Smith
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
@@ -30,6 +30,7 @@ GPTDataCL::GPTDataCL(void) {
 | 
			
		||||
   attributeOperation = backupFile = partName = hybrids = newPartInfo = NULL;
 | 
			
		||||
   mbrParts = twoParts = outDevice = typeCode = partGUID = diskGUID = NULL;
 | 
			
		||||
   alignment = DEFAULT_ALIGNMENT;
 | 
			
		||||
   alignEnd = false;
 | 
			
		||||
   deletePartNum = infoPartNum = largestPartNum = bsdPartNum = 0;
 | 
			
		||||
   tableSize = GPT_SIZE;
 | 
			
		||||
} // GPTDataCL constructor
 | 
			
		||||
@@ -90,6 +91,7 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
 | 
			
		||||
      {"randomize-guids", 'G', POPT_ARG_NONE, NULL, 'G', "randomize disk and partition GUIDs", ""},
 | 
			
		||||
      {"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...][:EE]"},
 | 
			
		||||
      {"info", 'i', POPT_ARG_INT, &infoPartNum, 'i', "show detailed information on partition", "partnum"},
 | 
			
		||||
      {"align-end", 'I', POPT_ARG_NONE, NULL, 'I', "align partition end points", ""},
 | 
			
		||||
      {"move-main-table", 'j', POPT_ARG_INT, &mainTableLBA, 'j', "adjust the location of the main partition table", "sector"},
 | 
			
		||||
      {"load-backup", 'l', POPT_ARG_STRING, &backupFile, 'l', "load GPT backup from file", "file"},
 | 
			
		||||
      {"list-types", 'L', POPT_ARG_NONE, NULL, 'L', "list known partition types", ""},
 | 
			
		||||
@@ -272,6 +274,9 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
 | 
			
		||||
               case 'i':
 | 
			
		||||
                  ShowPartDetails(infoPartNum - 1);
 | 
			
		||||
                  break;
 | 
			
		||||
               case 'I':
 | 
			
		||||
                  alignEnd = true;
 | 
			
		||||
                  break;
 | 
			
		||||
               case 'j':
 | 
			
		||||
                   if (MoveMainTable(mainTableLBA)) {
 | 
			
		||||
                       JustLooking(0);
 | 
			
		||||
@@ -307,9 +312,9 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
 | 
			
		||||
                     newPartNum = FindFirstFreePart();
 | 
			
		||||
                  low = FindFirstInLargest();
 | 
			
		||||
                  Align(&low);
 | 
			
		||||
                  high = FindLastInFree(low);
 | 
			
		||||
                  startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, low);
 | 
			
		||||
                  endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
 | 
			
		||||
                  high = FindLastInFree(low, alignEnd);
 | 
			
		||||
                  startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, sectorAlignment, low);
 | 
			
		||||
                  endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, sectorAlignment, high);
 | 
			
		||||
                  if (CreatePartition(newPartNum, startSector, endSector)) {
 | 
			
		||||
                     saveData = 1;
 | 
			
		||||
                  } else {
 | 
			
		||||
@@ -323,7 +328,7 @@ int GPTDataCL::DoOptions(int argc, char* argv[]) {
 | 
			
		||||
                  JustLooking(0);
 | 
			
		||||
                  startSector = FindFirstInLargest();
 | 
			
		||||
                  Align(&startSector);
 | 
			
		||||
                  endSector = FindLastInFree(startSector);
 | 
			
		||||
                  endSector = FindLastInFree(startSector, alignEnd);
 | 
			
		||||
                  if (largestPartNum <= 0)
 | 
			
		||||
                     largestPartNum = FindFirstFreePart() + 1;
 | 
			
		||||
                  if (CreatePartition(largestPartNum - 1, startSector, endSector)) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								gptcl.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								gptcl.h
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
    Implementation of GPTData class derivative with popt-based command
 | 
			
		||||
    line processing
 | 
			
		||||
    Copyright (C) 2010-2013 Roderick W. Smith
 | 
			
		||||
    Copyright (C) 2010-2022 Roderick W. Smith
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
@@ -34,6 +34,7 @@ class GPTDataCL : public GPTData {
 | 
			
		||||
      char *newPartInfo, *mbrParts, *twoParts, *outDevice, *typeCode;
 | 
			
		||||
      char *partGUID, *diskGUID;
 | 
			
		||||
      int alignment, deletePartNum, infoPartNum, largestPartNum, bsdPartNum;
 | 
			
		||||
      bool alignEnd;
 | 
			
		||||
      uint32_t tableSize;
 | 
			
		||||
      poptContext poptCon;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								gptcurses.cc
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								gptcurses.cc
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 *    Implementation of GPTData class derivative with curses-based text-mode
 | 
			
		||||
 *    interaction
 | 
			
		||||
 *    Copyright (C) 2011-2018 Roderick W. Smith
 | 
			
		||||
 *    Copyright (C) 2011-2022 Roderick W. Smith
 | 
			
		||||
 *
 | 
			
		||||
 *    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
 | 
			
		||||
@@ -430,12 +430,18 @@ void GPTDataCurses::Verify(void) {
 | 
			
		||||
 | 
			
		||||
// Create a new partition in the space pointed to by currentSpace.
 | 
			
		||||
void GPTDataCurses::MakeNewPart(void) {
 | 
			
		||||
   uint64_t size, newFirstLBA = 0, newLastLBA = 0;
 | 
			
		||||
   uint64_t size, newFirstLBA = 0, newLastLBA = 0, lastAligned;
 | 
			
		||||
   int partNum;
 | 
			
		||||
   char inLine[80];
 | 
			
		||||
 | 
			
		||||
   move(LINES - 4, 0);
 | 
			
		||||
   clrtobot();
 | 
			
		||||
   lastAligned = currentSpace->lastLBA + 1;
 | 
			
		||||
   Align(&lastAligned);
 | 
			
		||||
   lastAligned--;
 | 
			
		||||
   // Discard end-alignment attempt if it's giving us an invalid end point....
 | 
			
		||||
   if (!IsFree(lastAligned))
 | 
			
		||||
       lastAligned = currentSpace->lastLBA;
 | 
			
		||||
   while ((newFirstLBA < currentSpace->firstLBA) || (newFirstLBA > currentSpace->lastLBA)) {
 | 
			
		||||
      move(LINES - 4, 0);
 | 
			
		||||
      clrtoeol();
 | 
			
		||||
@@ -445,10 +451,13 @@ void GPTDataCurses::MakeNewPart(void) {
 | 
			
		||||
      echo();
 | 
			
		||||
      getnstr(inLine, 79);
 | 
			
		||||
      noecho();
 | 
			
		||||
      newFirstLBA = IeeeToInt(inLine, blockSize, currentSpace->firstLBA, currentSpace->lastLBA, newFirstLBA);
 | 
			
		||||
      newFirstLBA = IeeeToInt(inLine, blockSize, currentSpace->firstLBA, currentSpace->lastLBA, sectorAlignment, newFirstLBA);
 | 
			
		||||
      Align(&newFirstLBA);
 | 
			
		||||
   } // while
 | 
			
		||||
   size = currentSpace->lastLBA - newFirstLBA + 1;
 | 
			
		||||
   if (newFirstLBA > lastAligned)
 | 
			
		||||
      size = currentSpace->lastLBA - newFirstLBA + 1;
 | 
			
		||||
   else
 | 
			
		||||
      size = lastAligned - newFirstLBA + 1;
 | 
			
		||||
   while ((newLastLBA > currentSpace->lastLBA) || (newLastLBA < newFirstLBA)) {
 | 
			
		||||
      move(LINES - 3, 0);
 | 
			
		||||
      clrtoeol();
 | 
			
		||||
@@ -456,7 +465,7 @@ void GPTDataCurses::MakeNewPart(void) {
 | 
			
		||||
      echo();
 | 
			
		||||
      getnstr(inLine, 79);
 | 
			
		||||
      noecho();
 | 
			
		||||
      newLastLBA = newFirstLBA + IeeeToInt(inLine, blockSize, 1, size, size) - 1;
 | 
			
		||||
      newLastLBA = newFirstLBA + IeeeToInt(inLine, blockSize, 1, size, sectorAlignment, size) - 1;
 | 
			
		||||
   } // while
 | 
			
		||||
   partNum = FindFirstFreePart();
 | 
			
		||||
   if (CreatePartition(partNum, newFirstLBA, newLastLBA)) { // created OK; set type code & name....
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								gpttext.cc
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								gpttext.cc
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
    Copyright (C) 2010-2018  <Roderick W. Smith>
 | 
			
		||||
    Copyright (C) 2010-2022  <Roderick W. Smith>
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
@@ -199,7 +199,7 @@ void GPTDataTextUI::MoveMainTable(void) {
 | 
			
		||||
 | 
			
		||||
// Interactively create a partition
 | 
			
		||||
void GPTDataTextUI::CreatePartition(void) {
 | 
			
		||||
   uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector;
 | 
			
		||||
   uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector, lastAligned;
 | 
			
		||||
   uint32_t firstFreePart = 0;
 | 
			
		||||
   ostringstream prompt1, prompt2, prompt3;
 | 
			
		||||
   int partNum;
 | 
			
		||||
@@ -229,7 +229,7 @@ void GPTDataTextUI::CreatePartition(void) {
 | 
			
		||||
      prompt2 << "First sector (" << firstBlock << "-" << lastBlock << ", default = "
 | 
			
		||||
              << firstInLargest << ") or {+-}size{KMGTP}: ";
 | 
			
		||||
      do {
 | 
			
		||||
         sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, blockSize, prompt2.str());
 | 
			
		||||
         sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, prompt2.str());
 | 
			
		||||
      } while (IsFree(sector) == 0);
 | 
			
		||||
      origSector = sector;
 | 
			
		||||
      if (Align(§or)) {
 | 
			
		||||
@@ -239,15 +239,15 @@ void GPTDataTextUI::CreatePartition(void) {
 | 
			
		||||
         if (!beQuiet)
 | 
			
		||||
            cout << "Use 'l' on the experts' menu to adjust alignment\n";
 | 
			
		||||
      } // if
 | 
			
		||||
      //      Align(§or); // Align sector to correct multiple
 | 
			
		||||
      firstBlock = sector;
 | 
			
		||||
 | 
			
		||||
      // Get last block for new partitions...
 | 
			
		||||
      lastBlock = FindLastInFree(firstBlock);
 | 
			
		||||
      lastBlock = FindLastInFree(firstBlock, false);
 | 
			
		||||
      lastAligned = FindLastInFree(firstBlock, true);
 | 
			
		||||
      prompt3 << "Last sector (" << firstBlock << "-" << lastBlock << ", default = "
 | 
			
		||||
            << lastBlock << ") or {+-}size{KMGTP}: ";
 | 
			
		||||
              << lastAligned << ") or {+-}size{KMGTP}: ";
 | 
			
		||||
      do {
 | 
			
		||||
         sector = GetSectorNum(firstBlock, lastBlock, lastBlock, blockSize, prompt3.str());
 | 
			
		||||
         sector = GetSectorNum(firstBlock, lastBlock, lastAligned, prompt3.str());
 | 
			
		||||
      } while (IsFree(sector) == 0);
 | 
			
		||||
      lastBlock = sector;
 | 
			
		||||
 | 
			
		||||
@@ -548,6 +548,28 @@ int GPTDataTextUI::XFormToMBR(void) {
 | 
			
		||||
   return protectiveMBR.DoMenu();
 | 
			
		||||
} // GPTDataTextUI::XFormToMBR()
 | 
			
		||||
 | 
			
		||||
// Obtains a sector number, between low and high, from the
 | 
			
		||||
// user, accepting values prefixed by "+" to add sectors to low,
 | 
			
		||||
// or the same with "K", "M", "G", "T", or "P" as suffixes to add
 | 
			
		||||
// kibibytes, mebibytes, gibibytes, tebibytes, or pebibytes,
 | 
			
		||||
// respectively. If a "-" prefix is used, use the high value minus
 | 
			
		||||
// the user-specified number of sectors (or KiB, MiB, etc.). Use the
 | 
			
		||||
// def value as the default if the user just hits Enter.
 | 
			
		||||
uint64_t GPTDataTextUI::GetSectorNum(uint64_t low, uint64_t high, uint64_t def,
 | 
			
		||||
                                     const string & prompt) {
 | 
			
		||||
   uint64_t response;
 | 
			
		||||
   char line[255];
 | 
			
		||||
 | 
			
		||||
   do {
 | 
			
		||||
      cout << prompt;
 | 
			
		||||
      cin.getline(line, 255);
 | 
			
		||||
      if (!cin.good())
 | 
			
		||||
         exit(5);
 | 
			
		||||
      response = IeeeToInt(line, blockSize, low, high, sectorAlignment, def);
 | 
			
		||||
   } while ((response < low) || (response > high));
 | 
			
		||||
   return response;
 | 
			
		||||
} // GPTDataTextUI::GetSectorNum()
 | 
			
		||||
 | 
			
		||||
/******************************************************
 | 
			
		||||
 *                                                    *
 | 
			
		||||
 * Display informational messages for the user....    *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
    Implementation of GPTData class derivative with basic text-mode interaction
 | 
			
		||||
    Copyright (C) 2010-2018 Roderick W. Smith
 | 
			
		||||
    Copyright (C) 2010-2022 Roderick W. Smith
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
@@ -55,6 +55,7 @@ class GPTDataTextUI : public GPTData {
 | 
			
		||||
      void ShowDetails(void);
 | 
			
		||||
      void MakeHybrid(void);
 | 
			
		||||
      int XFormToMBR(void); // convert GPT to MBR, wiping GPT afterwards. Returns 1 if successful
 | 
			
		||||
      uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
 | 
			
		||||
 | 
			
		||||
      // An informational function....
 | 
			
		||||
      void WarnAboutIffyMBRPart(int partNum);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								sgdisk.8
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								sgdisk.8
									
									
									
									
									
								
							@@ -154,7 +154,10 @@ to sectors that are multiples of this value, which defaults to 1 MiB (2048
 | 
			
		||||
on disks with 512-byte sectors) on freshly formatted disks. This alignment
 | 
			
		||||
value is necessary to obtain optimum performance with Western Digital
 | 
			
		||||
Advanced Format and similar drives with larger physical than logical sector
 | 
			
		||||
sizes, with some types of RAID arrays, and with SSD devices.
 | 
			
		||||
sizes, with some types of RAID arrays, and with SSD devices. When the
 | 
			
		||||
\fI\-I\fR option is used, this same alignment value is used to determine
 | 
			
		||||
partition end points; but partitions end at one less than a multiple of this
 | 
			
		||||
value, to keep the partition length a multiple of this value.
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-A, \-\-attributes=list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]
 | 
			
		||||
@@ -280,7 +283,7 @@ is usually correct for Windows partitions. If the active/bootable flag should
 | 
			
		||||
be set, you must do so in another program, such as \fBfdisk\fR. The \fBgdisk\fR
 | 
			
		||||
program offers additional hybrid MBR creation options.
 | 
			
		||||
 | 
			
		||||
.TP 
 | 
			
		||||
.TP
 | 
			
		||||
.B \-i, \-\-info=partnum
 | 
			
		||||
Show detailed partition information. The summary information produced by
 | 
			
		||||
the \fI\-p\fR command necessarily omits many details, such as the partition's
 | 
			
		||||
@@ -288,6 +291,18 @@ unique GUID and the translation of \fBsgdisk\fR's
 | 
			
		||||
internal partition type code to a plain type name. The \fI\-i\fR option
 | 
			
		||||
displays this information for a single partition.
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-I, \-\-align\-end
 | 
			
		||||
When possible, align the end points of partitions to one less than a
 | 
			
		||||
multiple of the alignment value. When both start and end points are aligned,
 | 
			
		||||
partitions should be multiples of the alignment value in size, which is
 | 
			
		||||
necessary for some partition encryption tools to function correctly. This
 | 
			
		||||
option applies to all partitions created \fBafter\fR this option on the
 | 
			
		||||
command line. Note that this alignment is not always possible; for instance,
 | 
			
		||||
if the free space at the end of a disk is less than the alignment value,
 | 
			
		||||
with the current final partition being aligned, and if \fBsgdisk\fR is asked
 | 
			
		||||
to create a partition in that space, then it will \fBnot\fR be end\-aligned.
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-j, \-\-adjust\-main\-table=sector
 | 
			
		||||
Adjust the location of the main partition table. This value is normally 2,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								support.cc
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								support.cc
									
									
									
									
									
								
							@@ -3,7 +3,7 @@
 | 
			
		||||
// Primarily by Rod Smith, February 2009, but with a few functions
 | 
			
		||||
// copied from other sources (see attributions below).
 | 
			
		||||
 | 
			
		||||
/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
 | 
			
		||||
/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
 | 
			
		||||
  under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 | 
			
		||||
 | 
			
		||||
#define __STDC_LIMIT_MACROS
 | 
			
		||||
@@ -113,34 +113,11 @@ char GetYN(void) {
 | 
			
		||||
   return response;
 | 
			
		||||
} // GetYN(void)
 | 
			
		||||
 | 
			
		||||
// Obtains a sector number, between low and high, from the
 | 
			
		||||
// user, accepting values prefixed by "+" to add sectors to low,
 | 
			
		||||
// or the same with "K", "M", "G", "T", or "P" as suffixes to add
 | 
			
		||||
// kilobytes, megabytes, gigabytes, terabytes, or petabytes,
 | 
			
		||||
// respectively. If a "-" prefix is used, use the high value minus
 | 
			
		||||
// the user-specified number of sectors (or KiB, MiB, etc.). Use the
 | 
			
		||||
// def value as the default if the user just hits Enter. The sSize is
 | 
			
		||||
// the sector size of the device.
 | 
			
		||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize,
 | 
			
		||||
                      const string & prompt) {
 | 
			
		||||
   uint64_t response;
 | 
			
		||||
   char line[255];
 | 
			
		||||
 | 
			
		||||
   do {
 | 
			
		||||
      cout << prompt;
 | 
			
		||||
      cin.getline(line, 255);
 | 
			
		||||
      if (!cin.good())
 | 
			
		||||
         exit(5);
 | 
			
		||||
      response = IeeeToInt(line, sSize, low, high, def);
 | 
			
		||||
   } while ((response < low) || (response > high));
 | 
			
		||||
   return response;
 | 
			
		||||
} // GetSectorNum()
 | 
			
		||||
 | 
			
		||||
// Convert an IEEE-1541-2002 value (K, M, G, T, P, or E) to its equivalent in
 | 
			
		||||
// number of sectors. If no units are appended, interprets as the number
 | 
			
		||||
// of sectors; otherwise, interprets as number of specified units and
 | 
			
		||||
// converts to sectors. For instance, with 512-byte sectors, "1K" converts
 | 
			
		||||
// to 2. If value includes a "+", adds low and subtracts 1; if SIValue
 | 
			
		||||
// to 2. If value includes a "+", adds low and subtracts 1; if inValue
 | 
			
		||||
// inclues a "-", subtracts from high. If IeeeValue is empty, returns def.
 | 
			
		||||
// Returns final sector value. In case inValue is invalid, returns 0 (a
 | 
			
		||||
// sector value that's always in use on GPT and therefore invalid); and if
 | 
			
		||||
@@ -153,7 +130,7 @@ uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize,
 | 
			
		||||
// 0 values. The result is that IeeeToInt() returns UINT64_MAX when
 | 
			
		||||
// compiled with GCC (and so the value is rejected), whereas when VC++
 | 
			
		||||
// is used, the default value is returned.
 | 
			
		||||
uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def) {
 | 
			
		||||
uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint32_t sectorAlignment, uint64_t def) {
 | 
			
		||||
   uint64_t response = def, bytesPerUnit, mult = 1, divide = 1;
 | 
			
		||||
   size_t foundAt = 0;
 | 
			
		||||
   char suffix = ' ', plusFlag = ' ';
 | 
			
		||||
@@ -208,11 +185,12 @@ uint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high,
 | 
			
		||||
   } // if/elseif
 | 
			
		||||
 | 
			
		||||
   if (plusFlag == '+') {
 | 
			
		||||
      // Recompute response based on low part of range (if default == high
 | 
			
		||||
      // value, which should be the case when prompting for the end of a
 | 
			
		||||
      // range) or the defaut value (if default != high, which should be
 | 
			
		||||
      // the case for the first sector of a partition).
 | 
			
		||||
      if (def == high) {
 | 
			
		||||
      // Recompute response based on low part of range (if default is within
 | 
			
		||||
      // sectorAlignment sectors of high, which should be the case when
 | 
			
		||||
      // prompting for the end of a range) or the defaut value (if default is
 | 
			
		||||
      // further away from the high value, which should be the case for the
 | 
			
		||||
      // first sector of a partition).
 | 
			
		||||
      if ((high - def) < sectorAlignment) {
 | 
			
		||||
         if (response > 0)
 | 
			
		||||
            response--;
 | 
			
		||||
         if (response > (UINT64_MAX - low))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* This program is copyright (c) 2009-2018 by Roderick W. Smith. It is distributed
 | 
			
		||||
/* This program is copyright (c) 2009-2022 by Roderick W. Smith. It is distributed
 | 
			
		||||
  under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
 | 
			
		||||
 | 
			
		||||
#ifndef __GPTSUPPORT
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#define GPTFDISK_VERSION "1.0.8"
 | 
			
		||||
#define GPTFDISK_VERSION "1.0.8.2"
 | 
			
		||||
 | 
			
		||||
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
 | 
			
		||||
// Darwin (Mac OS) & FreeBSD: disk IOCTLs are different, and there is no lseek64
 | 
			
		||||
@@ -74,8 +74,7 @@ using namespace std;
 | 
			
		||||
string ReadString(void);
 | 
			
		||||
uint64_t GetNumber(uint64_t low, uint64_t high, uint64_t def, const string & prompt);
 | 
			
		||||
char GetYN(void);
 | 
			
		||||
uint64_t GetSectorNum(uint64_t low, uint64_t high, uint64_t def, uint64_t sSize, const std::string& prompt);
 | 
			
		||||
uint64_t IeeeToInt(string IeeeValue, uint64_t sSize, uint64_t low, uint64_t high, uint64_t def = 0);
 | 
			
		||||
uint64_t IeeeToInt(string IeeeValue, uint64_t sSize, uint64_t low, uint64_t high, uint32_t sectorAlignment, uint64_t def = 0);
 | 
			
		||||
string BytesToIeee(uint64_t size, uint32_t sectorSize);
 | 
			
		||||
unsigned char StrToHex(const string & input, unsigned int position);
 | 
			
		||||
int IsHex(string input); // Returns 1 if input can be hexadecimal number....
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user