Added -F option to sgdisk
diff --git a/NEWS b/NEWS
index ea356c0..7071eeb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,8 @@
 0.6.11 (??/??/2010):
 --------------------
 
-- Changed partition type code entry in gdisk so that it directly
-  accepts GUID values rather than requiring typing "0" to do so.
+- Streamlined GUID code entry in gdisk; it no longer offers the option
+  to enter GUIDs in separate segments.
 
 - The -t option to sgdisk now accepts GUID values as well as the
   sgdisk/gdisk-specific two-byte hex codes.
diff --git a/gdisk.cc b/gdisk.cc
index 3fde1e0..2da3623 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -318,6 +318,7 @@
    char* junk;
    uint32_t pn, temp1, temp2;
    int goOn = 1, i;
+   char guidStr[255];
    GUIDData aGUID;
    ostringstream prompt;
 
@@ -337,8 +338,14 @@
          case 'c': case 'C':
             if (theGPT->GetPartRange(&temp1, &temp2) > 0) {
                pn = theGPT->GetPartNum();
-               cout << "Enter the partition's new unique GUID:\n";
-               theGPT->SetPartitionGUID(pn, aGUID.GetGUIDFromUser());
+               cout << "Enter the partition's new unique GUID ('R' to randomize): ";
+               junk = fgets(guidStr, 255, stdin);
+               if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
+                  theGPT->SetPartitionGUID(pn, (GUIDData) guidStr);
+                  cout << "New GUID is " << theGPT->operator[](pn).GetUniqueGUID() << "\n";
+               } else {
+                  cout << "GUID is too short!\n";
+               } // if/else
             } else cout << "No partitions\n";
             break;
          case 'd': case 'D':
@@ -353,8 +360,13 @@
             theGPT->RandomizeGUIDs();
             break;
          case 'g': case 'G':
-            cout << "Enter the disk's unique GUID:\n";
-            theGPT->SetDiskGUID(aGUID.GetGUIDFromUser());
+            cout << "Enter the disk's unique GUID ('R' to randomize): ";
+            junk = fgets(guidStr, 255, stdin);
+            if ((strlen(guidStr) >= 33) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
+               theGPT->SetDiskGUID((GUIDData) guidStr);
+               cout << "The new disk GUID is " << theGPT->GetDiskGUID() << "\n";
+            } else
+               cout << "GUID is too short!\n";
             break;
          case 'h': case 'H':
             theGPT->RecomputeCHS();
diff --git a/gpt.cc b/gpt.cc
index 7ed1de3..78b1557 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -185,9 +185,9 @@
    } // if
    if ((mainHeader.diskGUID != secondHeader.diskGUID)) {
       problems++;
-      cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID.AsString()
+      cout << "\nProblem: main header's disk GUID (" << mainHeader.diskGUID
            << ") doesn't\nmatch the backup GPT header's disk GUID ("
-           << secondHeader.diskGUID.AsString() << ")\n"
+           << secondHeader.diskGUID << ")\n"
            << "You should use the 'b' or 'd' option on the recovery & transformation menu to\n"
            << "select one or the other header.\n";
    } // if
@@ -1268,7 +1268,7 @@
    cout << "Disk " << device << ": " << diskSize << " sectors, "
         << BytesToSI(diskSize * blockSize) << "\n";
    cout << "Logical sector size: " << blockSize << " bytes\n";
-   cout << "Disk identifier (GUID): " << mainHeader.diskGUID.AsString() << "\n";
+   cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
    cout << "Partition table holds up to " << numParts << " entries\n";
    cout << "First usable sector is " << mainHeader.firstUsableLBA
         << ", last usable sector is " << mainHeader.lastUsableLBA << "\n";
@@ -1661,9 +1661,14 @@
 // Returns 1 if the operation was successful, 0 if a problem was discovered.
 uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector) {
    int retval = 1; // assume there'll be no problems
+   uint64_t origSector = startSector;
 
    if (IsFreePartNum(partNum)) {
-      Align(&startSector); // Align sector to correct multiple
+      if (Align(&startSector)) {
+         cout << "Information: Moved requested sector from " << origSector << " to "
+              << startSector << " in\norder to align on " << sectorAlignment
+              << "-sector boundaries.\n";
+      } // if
       if (IsFree(startSector) && (startSector <= endSector)) {
          if (FindLastInFree(startSector) >= endSector) {
             partitions[partNum].SetFirstLBA(startSector);
@@ -1891,7 +1896,6 @@
 
    if ((*sector % sectorAlignment) != 0) {
       original = *sector;
-      retval = 1;
       earlier = (*sector / sectorAlignment) * sectorAlignment;
       later = earlier + (uint64_t) sectorAlignment;
 
@@ -1905,6 +1909,7 @@
          } while ((sectorOK == 1) && (testSector < *sector));
          if (sectorOK == 1) {
             *sector = earlier;
+            retval = 1;
          } // if
       } // if firstUsableLBA check
 
@@ -1917,25 +1922,9 @@
          } while ((sectorOK == 1) && (testSector > *sector));
          if (sectorOK == 1) {
             *sector = later;
+            retval = 1;
          } // if
       } // if
-
-      // If sector was changed successfully, inform the user of this fact.
-      // Otherwise, notify the user that it couldn't be done....
-      if (sectorOK == 1) {
-         cout << "Information: Moved requested sector from " << original << " to "
-              << *sector << " in\norder to align on " << sectorAlignment
-              << "-sector boundaries.\n";
-         if (!beQuiet)
-            cout << "Use 'l' on the experts' menu to adjust alignment\n";
-      } else {
-         cout << "Information: Sector not aligned on " << sectorAlignment
-              << "-sector boundary and could not be moved.\n"
-              << "If you're using a Western Digital Advanced Format or similar disk with\n"
-              << "underlying 4096-byte sectors or certain types of RAID array, performance\n"
-              << "may suffer.\n";
-         retval = 0;
-      } // if/else
    } // if
    return retval;
 } // GPTData::Align()
@@ -2259,12 +2248,27 @@
 // Validate partition number
 bool GPTData::ValidPartNum (const uint32_t partNum) {
    if (partNum >= numParts) {
-      cerr << "Partition number out of range: " << (signed) partNum << endl;
+      cerr << "Partition number out of range: " << partNum << "\n";
       return false;
    } // if
    return true;
 } // GPTData::ValidPartNum
 
+// Return a single partition for inspection (not modification!) by other
+// functions.
+const GPTPart & GPTData::operator[](uint32_t partNum) const {
+   if (partNum >= numParts) {
+      cerr << "Partition number out of range: " << partNum << "\n";
+      partNum = 0;
+   } // if
+   return partitions[partNum];
+} // operator[]
+
+// Return (not for modification!) the disk's GUID value
+const GUIDData & GPTData::GetDiskGUID(void) const {
+   return mainHeader.diskGUID;
+} // GPTData::GetDiskGUID()
+
 // Manage attributes for a partition, based on commands passed to this function.
 // (Function is non-interactive.)
 // Returns 1 if a modification command succeeded, 0 if the command should not have
diff --git a/gpt.h b/gpt.h
index 2bf3acb..115ce4f 100644
--- a/gpt.h
+++ b/gpt.h
@@ -16,7 +16,7 @@
 #ifndef __GPTSTRUCTS
 #define __GPTSTRUCTS
 
-#define GPTFDISK_VERSION "0.6.11-pre2"
+#define GPTFDISK_VERSION "0.6.11-pre3"
 
 // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest-
 // numbered value to refer to partition numbers. (Most will be 0 or positive,
@@ -177,10 +177,10 @@
    uint64_t GetSecondPartsLBA(void) {return secondHeader.partitionEntriesLBA;}
    uint64_t GetFirstUsableLBA(void) {return mainHeader.firstUsableLBA;}
    uint64_t GetLastUsableLBA(void) {return mainHeader.lastUsableLBA;}
-   uint64_t GetPartFirstLBA(uint32_t i) {return partitions[i].GetFirstLBA();}
-   uint64_t GetPartLastLBA(uint32_t i) {return partitions[i].GetLastLBA();}
    uint32_t CountParts(void);
    bool ValidPartNum (const uint32_t partNum);
+   const GPTPart & operator[](uint32_t partNum) const;
+   const GUIDData & GetDiskGUID(void) const;
 
    // Find information about free space
    uint64_t FindFirstAvailable(uint64_t start = 0);
diff --git a/gptpart.cc b/gptpart.cc
index f597ca0..cea8362 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -177,9 +177,9 @@
    uint64_t size;
 
    if (firstLBA != 0) {
-      cout << "Partition GUID code: " << partitionType.AsString();
+      cout << "Partition GUID code: " << partitionType;
       cout << " (" << partitionType.TypeName() << ")\n";
-      cout << "Partition unique GUID: " << uniqueGUID.AsString() << "\n";
+      cout << "Partition unique GUID: " << uniqueGUID << "\n";
 
       cout << "First sector: " << firstLBA << " (at "
             << BytesToSI(firstLBA * blockSize) << ")\n";
diff --git a/gptpart.h b/gptpart.h
index 7ae1260..7ed6702 100644
--- a/gptpart.h
+++ b/gptpart.h
@@ -53,9 +53,9 @@
       PartType & GetType(void) {return partitionType;}
       uint16_t GetHexType(void);
       string GetTypeName(void);
-      GUIDData GetUniqueGUID(void) {return uniqueGUID;}
-      uint64_t GetFirstLBA(void) {return firstLBA;}
-      uint64_t GetLastLBA(void) {return lastLBA;}
+      const GUIDData GetUniqueGUID(void) const {return uniqueGUID;}
+      uint64_t GetFirstLBA(void) const {return firstLBA;}
+      uint64_t GetLastLBA(void) const {return lastLBA;}
       uint64_t GetLengthLBA(void);
       uint64_t GetAttributes(void) {return attributes;}
       string GetDescription(void);
diff --git a/gpttext.cc b/gpttext.cc
index c37e01e..b9039d3 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -180,7 +180,7 @@
 
 // Interactively create a partition
 void GPTDataTextUI::CreatePartition(void) {
-   uint64_t firstBlock, firstInLargest, lastBlock, sector;
+   uint64_t firstBlock, firstInLargest, lastBlock, sector, origSector;
    uint32_t firstFreePart = 0;
    ostringstream prompt1, prompt2, prompt3;
    int partNum;
@@ -211,7 +211,15 @@
       do {
          sector = GetSectorNum(firstBlock, lastBlock, firstInLargest, prompt2.str());
       } while (IsFree(sector) == 0);
-      Align(&sector); // Align sector to correct multiple
+      origSector = sector;
+      if (Align(&sector)) {
+         cout << "Information: Moved requested sector from " << origSector << " to "
+              << sector << " in\norder to align on " << sectorAlignment
+              << "-sector boundaries.\n";
+         if (!beQuiet)
+            cout << "Use 'l' on the experts' menu to adjust alignment\n";
+      } // if
+      //      Align(&sector); // Align sector to correct multiple
       firstBlock = sector;
 
       // Get last block for new partitions...
diff --git a/gpttext.h b/gpttext.h
index f71e61b..6d91a13 100644
--- a/gpttext.h
+++ b/gpttext.h
@@ -32,6 +32,9 @@
       GPTDataTextUI(string filename);
       ~GPTDataTextUI(void);
 
+      // This one needs to be explicitly defined, even though it does nothing new....
+      const GPTPart & operator[](uint32_t partNum) {return GPTData::operator[](partNum);}
+
       // Extended (interactive) versions of some base-class functions
       WhichToUse UseWhichPartitions(void);
       int XFormDisklabel(void);
diff --git a/guid.cc b/guid.cc
index 9a55765..11e02d4 100644
--- a/guid.cc
+++ b/guid.cc
@@ -15,6 +15,7 @@
 #define __STDC_CONSTANT_MACROS
 
 #include <stdio.h>
+#include <time.h>
 #include <string>
 #include <iostream>
 #include "guid.h"
@@ -23,6 +24,7 @@
 using namespace std;
 
 GUIDData::GUIDData(void) {
+   srand(time(0));
    Zero();
 } // constructor
 
@@ -119,52 +121,6 @@
    return operator=((string) orig);
 } // GUIDData::operator=(const char * orig)
 
-// Read a GUIDData from stdin, prompting the user along the way for the
-// correct form. This is a bit more flexible than it claims; it parses
-// any entry of 32 or 36 characters as a GUID (
-GUIDData & GUIDData::GetGUIDFromUser(void) {
-   string part1, part2, part3, part4, part5;
-   char line[255];
-   int entered = 0;
-
-   cout << "\nA GUID is entered in five segments of from two to six bytes, with\n"
-        << "dashes between segments.\n";
-   cout << "Enter the entire GUID, a four-byte hexadecimal number for the first segment, or\n"
-        << "'R' to generate the entire GUID randomly: ";
-   cin.get(line, 255);
-   part1 = DeleteSpaces(line);
-
-   // If user entered 'r' or 'R', generate GUID randomly....
-   if ((part1[0] == 'r') || (part1[0] == 'R')) {
-      Randomize();
-      entered = 1;
-   } // if user entered 'R' or 'r'
-
-   // If string length is right for whole entry, try to parse it....
-   if (((part1.length() == 36) || (part1.length() == 32)) && (entered == 0)) {
-      operator=(part1);
-      entered = 1;
-   } // if
-
-   // If neither of the above methods of entry was used, use prompted
-   // entry....
-   if (entered == 0) {
-      cout << "Enter a two-byte hexadecimal number for the second segment: ";
-      cin >> part2;
-      cout << "Enter a two-byte hexadecimal number for the third segment: ";
-      cin >> part3;
-      cout << "Enter a two-byte hexadecimal number for the fourth segment: ";
-      cin >> part4;
-      cout << "Enter a six-byte hexadecimal number for the fifth segment: ";
-      cin >> part5;
-      operator=(part1 += (string) "-" += part2 += (string) "-" += part3
-                += (string) "-" += part4 += (string) "-" += part5);
-   } // if/else
-   cin.ignore(255, '\n');
-   cout << "New GUID: " << AsString() << "\n";
-   return *this;
-} // GUIDData::GetGUIDData(void)
-
 // Erase the contents of the GUID
 void GUIDData::Zero(void) {
    int i;
@@ -189,12 +145,12 @@
 #else
    int i;
    for (i = 0; i < 16; i++)
-      uuidData[i] = rand();
+      uuidData[i] = (unsigned char) (256.0 * (rand() / (RAND_MAX + 1.0)));
 #endif
 } // GUIDData::Randomize
 
 // Equality operator; returns 1 if the GUIDs are equal, 0 if they're unequal
-int GUIDData::operator==(const GUIDData & orig) {
+int GUIDData::operator==(const GUIDData & orig) const {
    int retval = 1; // assume they're equal
    int i;
 
@@ -206,12 +162,12 @@
 } // GUIDData::operator==
 
 // Inequality operator; returns 1 if the GUIDs are unequal, 0 if they're equal
-int GUIDData::operator!=(const GUIDData & orig) {
+int GUIDData::operator!=(const GUIDData & orig) const {
    return !operator==(orig);
 } // GUIDData::operator!=
 
 // Return the GUID as a string, suitable for display to the user.
-string GUIDData::AsString(void) {
+string GUIDData::AsString(void) const {
    char theString[40];
 
    sprintf(theString,
@@ -237,3 +193,17 @@
    } // if
    return s;
 } // GUIDData::DeleteSpaces()
+
+/*******************************
+ *                             *
+ * Non-class support functions *
+ *                             *
+ *******************************/
+
+// Display a GUID as a string....
+ostream & operator<<(ostream & os, const GUIDData & data) {
+   string asString;
+
+   os << data.AsString();
+   return os;
+} // GUIDData::operator<<()
\ No newline at end of file
diff --git a/guid.h b/guid.h
index f5953ca..d22ec86 100644
--- a/guid.h
+++ b/guid.h
@@ -44,16 +44,17 @@
       GUIDData & operator=(const GUIDData & orig);
       GUIDData & operator=(const string & orig);
       GUIDData & operator=(const char * orig);
-      GUIDData & GetGUIDFromUser(void);
       void Zero(void);
       void Randomize(void);
 
       // Data tests....
-      int operator==(const GUIDData & orig);
-      int operator!=(const GUIDData & orig);
+      int operator==(const GUIDData & orig) const;
+      int operator!=(const GUIDData & orig) const;
 
       // Data retrieval....
-      string AsString(void);
+      string AsString(void) const;
 }; // class GUIDData
 
+ostream & operator<<(ostream & os, const GUIDData & data);
+
 #endif
diff --git a/parttypes.cc b/parttypes.cc
index a9cdf79..37f47a7 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -238,7 +238,7 @@
 } // PartType::operator=(uint16_t ID)
 
 // Return the English description of the partition type (e.g., "Linux/Windows data")
-string PartType::TypeName(void) {
+string PartType::TypeName(void) const {
    AType* theItem = allTypes;
    int found = 0;
    string typeName;
@@ -262,7 +262,7 @@
 // is set to 0. This enables control of which values get returned when
 // there are multiple possibilities, but opens the algorithm up to the
 // potential for problems should the data in the list be bad.
-uint16_t PartType::GetHexType() {
+uint16_t PartType::GetHexType() const {
    AType* theItem = allTypes;
    int found = 0;
    uint16_t theID = 0xFFFF;
@@ -285,7 +285,7 @@
 // Note: This function assumes an 80-column display. On wider displays,
 // it stops at under 80 columns; on narrower displays, lines will wrap
 // in an ugly way.
-void PartType::ShowAllTypes(void) {
+void PartType::ShowAllTypes(void) const {
    int colCount = 1; // column count
    size_t i;
    AType* thisType = allTypes;
@@ -312,7 +312,7 @@
 } // PartType::ShowTypes()
 
 // Returns 1 if code is a valid extended MBR code, 0 if it's not
-int PartType::Valid(uint16_t code) {
+int PartType::Valid(uint16_t code) const {
    AType* thisType = allTypes;
    int found = 0;
 
diff --git a/parttypes.h b/parttypes.h
index 4d6e547..9f38b76 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -50,12 +50,12 @@
    PartType & operator=(uint16_t ID); // Use MBR type code times 0x0100 to assign GUID
 
    // Retrieve transformed GUID data based on type code matches
-   string TypeName(void);
-   uint16_t GetHexType();
+   string TypeName(void) const;
+   uint16_t GetHexType() const;
 
    // Information relating to all type data
-   void ShowAllTypes(void);
-   int Valid(uint16_t);
+   void ShowAllTypes(void) const;
+   int Valid(uint16_t code) const;
 };
 
 #endif
diff --git a/sgdisk.cc b/sgdisk.cc
index b829d3c..7b88f71 100644
--- a/sgdisk.cc
+++ b/sgdisk.cc
@@ -25,7 +25,7 @@
 
 #define MAX_OPTIONS 50
 
-int BuildMBR(GPTData* theGPT, char* argument, int isHybrid);
+int BuildMBR(GPTData& theGPT, char* argument, int isHybrid);
 int CountColons(char* argument);
 
 int main(int argc, char *argv[]) {
@@ -37,6 +37,7 @@
    int alignment = DEFAULT_ALIGNMENT, retval = 0, pretend = 0;
    uint32_t tableSize = 128;
    uint64_t startSector, endSector;
+   uint64_t temp; // temporary variable; free to use in any case
    char *attributeOperation = NULL;
    char *device = NULL;
    char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
@@ -58,6 +59,7 @@
       {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second header to end of disk", ""},
       {"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""},
       {"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""},
+      {"first-aligned-in-largest", 'F', POPT_ARG_NONE, NULL, 'F', "show start of the largest free block, aligned", ""},
       {"mbrtogpt", 'g', POPT_ARG_NONE, NULL, 'g', "convert MBR to GPT", ""},
       {"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...]"},
@@ -195,6 +197,11 @@
                case 'f':
                   cout << theGPT.FindFirstInLargest() << "\n";
                   break;
+               case 'F':
+                  temp = theGPT.FindFirstInLargest();
+                  theGPT.Align(&temp);
+                  cout << temp << "\n";
+                  break;
                case 'g':
                   theGPT.JustLooking(0);
                   saveData = 1;
@@ -207,7 +214,7 @@
                   break;
                case 'h':
                   theGPT.JustLooking(0);
-                  if (BuildMBR(&theGPT, hybrids, 1) == 1)
+                  if (BuildMBR(theGPT, hybrids, 1) == 1)
                      saveData = 1;
                   break;
                case 'i':
@@ -227,7 +234,7 @@
                   break;
                case 'm':
                   theGPT.JustLooking(0);
-                  if (BuildMBR(&theGPT, mbrParts, 0) == 1) {
+                  if (BuildMBR(theGPT, mbrParts, 0) == 1) {
                      if (!pretend) {
                         if (theGPT.SaveMBR())
                            theGPT.DestroyGPT();
@@ -399,12 +406,12 @@
 } // main
 
 // Create a hybrid or regular MBR from GPT data structures
-int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) {
+int BuildMBR(GPTData & theGPT, char* argument, int isHybrid) {
    int numParts, allOK = 1, i;
    PartNotes notes;
    struct PartInfo *newNote;
 
-   if ((theGPT != NULL) && (argument != NULL)) {
+   if ((&theGPT != NULL) && (argument != NULL)) {
       numParts = CountColons(argument) + 1;
       if (numParts <= (4 - isHybrid)) {
          for (i = 0; i < numParts; i++) {
@@ -413,8 +420,8 @@
             newNote->active = 0;
             newNote->hexCode = 0; // code to compute it from default
             newNote->type = PRIMARY;
-            newNote->firstLBA = theGPT->GetPartFirstLBA(newNote->gptPartNum);
-            newNote->lastLBA = theGPT->GetPartLastLBA(newNote->gptPartNum);
+            newNote->firstLBA = theGPT[newNote->gptPartNum].GetFirstLBA();
+            newNote->lastLBA = theGPT[newNote->gptPartNum].GetLastLBA();
             notes.AddToEnd(newNote);
          } // for
          if (isHybrid) {
@@ -426,7 +433,7 @@
             // newNote firstLBA and lastLBA are computed later...
             notes.AddToStart(newNote);
          } // if
-         if (theGPT->PartsToMBR(notes) != numParts)
+         if (theGPT.PartsToMBR(notes) != numParts)
             allOK = 0;
       } else allOK = 0;
    } else allOK = 0;