Updates for version 0.4.2

New feature: Ability to edit disk images.
Several small bug fixes and feature enhancements (see CHANGELOG).
diff --git a/CHANGELOG b/CHANGELOG
index 8f6f69a..0cf5148 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,30 @@
+0.4.2:
+------
+
+- Code cleanup.
+
+- Fixed very small formatting bug in display of hex code when a match isn't
+  found when converting from an MBR/gdisk hex code to a GUID type code.
+
+- Added the ability to work on disk image files (raw files for virtual
+  machines, backup images, etc.). The program assumes that all such disk
+  image files have 512-byte sectors.
+
+- Added verification prompt to 'o' main-menu option to avoid accidental
+  erasures of all partitions.
+
+- The "destroy GPT data structures" option ('z' on the experts' menu) now
+  also destroys all EFI GPT (0xEE) partitions in the MBR.
+
+- Added an extra warning to the "destroy GPT data structures" option if an APM
+  or BSD disklabel was detected on the disk.
+
+- Added a buffer flush after destroying GPT data structures, to get the OS
+  to read the new (empty or MBR-only) partition table.
+
+- Fixed bug that allowed entry of nonexistent partition numbers when creating
+  a hybrid MBR.
+
 0.4.1:
 ------
 
diff --git a/Makefile b/Makefile
index a6eec4f..f9467ed 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 CXX=g++
 #CFLAGS=-O2 -fpack-struct
 CFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
-CXXFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
-LIB_NAMES=support crc32 gptpart mbr gpt bsd parttypes attributes
+CXXFLAGS=-O2 -fpack-struct -Wuninitialized -Wreturn-type -D_FILE_OFFSET_BITS=64 -g
+LIB_NAMES=crc32 support gptpart mbr gpt bsd parttypes attributes
 LIB_SRCS=$(NAMES:=.cc)
 LIB_OBJS=$(LIB_NAMES:=.o)
 LIB_HEADERS=$(LIB_NAMES:=.h)
diff --git a/attributes.h b/attributes.h
index 14329c6..38313d7 100644
--- a/attributes.h
+++ b/attributes.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <string>
+#include <string.h>
 #include "support.h"
 
 #ifndef __GPT_ATTRIBUTES
diff --git a/bsd.cc b/bsd.cc
index 4bc28f4..e03a98c 100644
--- a/bsd.cc
+++ b/bsd.cc
@@ -64,7 +64,6 @@
 // file, starting with the specified sector number.
 void BSDData::ReadBSDData(int fd, uint64_t startSector, uint64_t endSector) {
    uint8_t buffer[2048]; // I/O buffer
-   uint64_t startByte;
    int i, err, foundSig = 0, bigEnd = 0;
    int relative = 0; // assume absolute partition sector numbering
    uint32_t realSig;
diff --git a/gdisk.8 b/gdisk.8
index 9cdfdc8..143869c 100644
--- a/gdisk.8
+++ b/gdisk.8
@@ -1,6 +1,6 @@
 .\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
 .\" May be distributed under the GNU General Public License
-.TH GDISK 8 "August 2009" "0.4.1" "GPT fdisk Manual"
+.TH GDISK 8 "August 2009" "0.4.2" "GPT fdisk Manual"
 .SH NAME
 gdisk \- GPT partition table manipulator for Linux and Unix
 .SH SYNOPSIS
@@ -425,7 +425,7 @@
 Set attributes. GPT provides a 64-bit attributes field that can be used to
 set partition features.
 .B gdisk
-supports four attributes: 
+supports four attributes:
 .IR "system partition",
 .IR "read-only",
 .IR "hidden",
@@ -548,7 +548,7 @@
 .TP
 .B z
 Destroy the GPT data structures and exit. Use this option if you want to
-repartition a GPT disk using 
+repartition a GPT disk using
 .B "fdisk"
 or some other GPT-unaware program.
 You'll be given the choice of preserving the existing MBR, in case it's a
@@ -562,7 +562,7 @@
 usually bypasses the prompt entirely.
 
 .SH BUGS
-As of August of 2009 (version 0.4.1),
+As of September 2009 (version 0.4.2),
 .B gdisk
 should be considered beta software. Known bugs and limitations include:
 
diff --git a/gdisk.cc b/gdisk.cc
index ad2f51b..dcc2c51 100644
--- a/gdisk.cc
+++ b/gdisk.cc
@@ -27,7 +27,7 @@
    int doMore = 1;
    char* device = NULL;
 
-   printf("GPT fdisk (gdisk) version 0.4.1\n\n");
+   printf("GPT fdisk (gdisk) version 0.4.2\n\n");
 
     if (argc == 2) { // basic usage
       if (SizesOK()) {
@@ -90,9 +90,12 @@
          theGPT->CreatePartition();
          break;
       case 'o': case 'O':
-         theGPT->ClearGPTData();
-         theGPT->MakeProtectiveMBR();
-//         theGPT->BlankPartitions();
+         printf("This option deletes all partitions and creates a new "
+                "protective MBR.\nProceed? ");
+         if (GetYN() == 'Y') {
+            theGPT->ClearGPTData();
+            theGPT->MakeProtectiveMBR();
+         } // if
          break;
       case 'p': case 'P':
          theGPT->DisplayGPTData();
diff --git a/gpt.cc b/gpt.cc
index 9498a86..3b7f9d9 100644
--- a/gpt.cc
+++ b/gpt.cc
@@ -83,7 +83,7 @@
 // do *NOT* recover from these problems. Returns the total number of
 // problems identified.
 int GPTData::Verify(void) {
-   int problems = 0, numSegments, i, j;
+   int problems = 0, numSegments;
    uint64_t totalFree, largestSegment;
    char tempStr[255], siTotal[255], siLargest[255];
 
@@ -282,7 +282,7 @@
    } // if/else/if
 
    // If MBR bad, check for an Apple disk signature
-   if ((protectiveMBR.GetValidity() == invalid) && 
+   if ((protectiveMBR.GetValidity() == invalid) &&
         (((mainHeader.signature << 32) == APM_SIGNATURE1) ||
         (mainHeader.signature << 32) == APM_SIGNATURE2)) {
       apmFound = 1; // Will display warning message later
@@ -317,7 +317,7 @@
 // byte order on big-endian systems) if any changes have been made.
 void GPTData::RecomputeCRCs(void) {
    uint32_t crc;
-   uint32_t trueNumParts, crcTemp;
+   uint32_t trueNumParts;
    int littleEndian = 1;
 
    // Initialize CRC functions...
@@ -703,7 +703,7 @@
 // Writes GPT (and protective MBR) to disk. Returns 1 on successful
 // write, 0 if there was a problem.
 int GPTData::SaveGPTData(void) {
-   int allOK = 1, i, j;
+   int allOK = 1, i;
    char answer, line[256];
    int fd;
    uint64_t secondTable;
@@ -806,27 +806,7 @@
 
          // re-read the partition table
          if (allOK) {
-            sync();
-#ifdef __APPLE__
-            printf("Warning: The kernel may continue to use old or deleted partitions.\n"
-                  "You should reboot or remove the drive.\n");
-	    /* don't know if this helps
-	     * it definitely will get things on disk though:
-            * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
-            i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
-#else
-#ifdef __FreeBSD__
-            sleep(2);
-            i = ioctl(fd, DIOCGFLUSH);
-            printf("Warning: The kernel may still provide disk access using old partition IDs.\n");
-#else
-            sleep(2);
-            i = ioctl(fd, BLKRRPART);
-            if (i)
-               printf("Warning: The kernel is still using the old partition table.\n"
-                     "The new table will be used at the next reboot.\n");
-#endif
-#endif
+            DiskSync(fd);
          } // if
 
          if (allOK) { // writes completed OK
@@ -1035,7 +1015,7 @@
 
 // Display the basic GPT data
 void GPTData::DisplayGPTData(void) {
-   int i, j;
+   int i;
    char sizeInSI[255]; // String to hold size of disk in SI units
    char tempStr[255];
    uint64_t temp, totalFree;
@@ -1233,13 +1213,17 @@
 // This function destroys the on-disk GPT structures. Returns 1 if the
 // user confirms destruction, 0 if the user aborts.
 int GPTData::DestroyGPT(void) {
-   int fd, i, doMore;
+   int fd, i;
    char blankSector[512], goOn;
 
    for (i = 0; i < 512; i++) {
       blankSector[i] = '\0';
    } // for
 
+   if ((apmFound) || (bsdFound)) {
+      printf("WARNING: APM or BSD disklabel structures detected! This operation could\n"
+             "damage any APM or BSD partitions on this disk!\n");
+   } // if APM or BSD
    printf("\a\aAbout to wipe out GPT on %s. Proceed? ", device);
    goOn = GetYN();
    if (goOn == 'Y') {
@@ -1265,7 +1249,16 @@
          if (GetYN() == 'Y') {
             lseek64(fd, 0, SEEK_SET);
             write(fd, blankSector, 512); // blank it out
-         } // if blank MBR
+         } else { // write current protective MBR, in case it's hybrid....
+            // find and delete 0xEE partitions in MBR
+            for (i = 0; i < 4; i++) {
+               if (protectiveMBR.GetType(i) == (uint8_t) 0xEE) {
+                  protectiveMBR.DeletePartition(i);
+               } // if
+            } // for
+            protectiveMBR.WriteMBRData(fd);
+         } // if/else
+         DiskSync(fd);
          close(fd);
          printf("GPT data structures destroyed! You may now partition the disk using fdisk or\n"
                "other utilities. Program will now terminate.\n");
@@ -1376,7 +1369,6 @@
    int i, numToConvert;
    uint8_t origType;
    struct newGUID;
-   char name[NAME_SIZE];
 
    // Clear out old data & prepare basics....
    ClearGPTData();
@@ -1391,7 +1383,7 @@
       origType = protectiveMBR.GetType(i);
       // don't waste CPU time trying to convert extended, hybrid protective, or
       // null (non-existent) partitions
-      if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) && 
+      if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
            (origType != 0x00) && (origType != 0xEE))
          partitions[i] = protectiveMBR.AsGPT(i);
    } // for
@@ -1509,7 +1501,8 @@
       j = partNums[i] - 1;
       printf("\nCreating entry for partition #%d\n", j + 1);
       if ((j >= 0) && (j < mainHeader.numParts)) {
-         if (partitions[j].GetLastLBA() < UINT32_MAX) {
+         if ((partitions[j].GetLastLBA() < UINT32_MAX) &&
+             (partitions[j].GetLastLBA() > UINT64_C(0))) {
             do {
                printf("Enter an MBR hex code (default %02X): ",
                       typeHelper.GUIDToID(partitions[j].GetType()) / 256);
@@ -1529,7 +1522,8 @@
                                    (uint32_t) length, typeCode, bootable);
             protectiveMBR.SetHybrid();
          } else { // partition out of range
-            printf("Partition %d ends beyond the 2TiB limit of MBR partitions; omitting it.\n",
+            printf("Partition %d ends beyond the 2TiB limit of MBR partitions or does not exist;\n"
+                   "omitting it.\n",
                    j + 1);
          } // if/else
       } else {
@@ -1683,8 +1677,12 @@
 
 // Set up data structures for entirely new set of partitions on the
 // specified device. Returns 1 if OK, 0 if there were problems.
+// Note that this function does NOT clear the protectiveMBR data
+// structure, since it may hold the original MBR partitions if the
+// program was launched on an MBR disk, and those may need to be
+// converted to GPT format.
 int GPTData::ClearGPTData(void) {
-   int goOn, i;
+   int goOn = 1, i;
 
    // Set up the partition table....
    free(partitions);
@@ -1835,7 +1833,7 @@
 // Finds the first available sector in the largest block of unallocated
 // space on the disk. Returns 0 if there are no available blocks left
 uint64_t GPTData::FindFirstInLargest(void) {
-   uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment;
+   uint64_t start, firstBlock, lastBlock, segmentSize, selectedSize = 0, selectedSegment = 0;
 
    start = 0;
    do {
@@ -1937,7 +1935,7 @@
          isFree = 0;
            } // if
    } // for
-   if ((sector < mainHeader.firstUsableLBA) || 
+   if ((sector < mainHeader.firstUsableLBA) ||
         (sector > mainHeader.lastUsableLBA)) {
       isFree = 0;
         } // if
diff --git a/gptpart.cc b/gptpart.cc
index cb622d3..671e42e 100644
--- a/gptpart.cc
+++ b/gptpart.cc
@@ -68,6 +68,7 @@
    attributes = orig.attributes;
    for (i = 0; i < NAME_SIZE; i++)
       name[i] = orig.name[i];
+   return *this;
 } // assignment operator
 
 // Sets the unique GUID to a value of 0 or a random value,
diff --git a/mbr.cc b/mbr.cc
index 28745b3..4e789e1 100644
--- a/mbr.cc
+++ b/mbr.cc
@@ -179,11 +179,12 @@
 
    // Find block size
    if (checkBlockSize) {
-      if ((blockSize = GetBlockSize(fd)) == -1) {
-         blockSize = SECTOR_SIZE;
-         printf("Unable to determine sector size; assuming %lu bytes!\n",
-               (unsigned long) SECTOR_SIZE);
-      } // if
+      blockSize = GetBlockSize(fd);
+//      if ((blockSize = GetBlockSize(fd)) == -1) {
+//         blockSize = SECTOR_SIZE;
+//         printf("Unable to determine sector size; assuming %lu bytes!\n",
+//               (unsigned long) SECTOR_SIZE);
+//      } // if
    } // if (checkBlockSize)
 
    // Load logical partition data, if any is found....
@@ -291,6 +292,7 @@
    } // for i...
 
    // Now write that data structure...
+   lseek64(fd, 0, SEEK_SET);
    write(fd, &tempMBR, 512);
 
 /*   write(fd, code, 440);
@@ -298,7 +300,7 @@
    write(fd, &nulls, 2);
    write(fd, partitions, 64);
    write(fd, &MBRSignature, 2); */
-   
+
    // Reverse the byte order back, if necessary
    if (IsLittleEndian() == 0) {
       ReverseBytes(&diskSignature, 4);
@@ -496,6 +498,20 @@
    return found;
 } // MBRData::MakeBiggestPart(int i)
 
+// Delete partition #i
+void MBRData::DeletePartition(int i) {
+   int j;
+
+   partitions[i].firstLBA = UINT32_C(0);
+   partitions[i].lengthLBA = UINT32_C(0);
+   partitions[i].status = UINT8_C(0);
+   partitions[i].partitionType = UINT8_C(0);
+   for (j = 0; j < 3; j++) {
+      partitions[i].firstSector[j] = UINT8_C(0);
+      partitions[i].lastSector[j] = UINT8_C(0);
+   } // for j (CHS data blanking)
+} // MBRData::DeletePartition()
+
 // Delete a partition if one exists at the specified location.
 // Returns 1 if a partition was deleted, 0 otherwise....
 // Used to help keep GPT & hybrid MBR partitions in sync....
@@ -509,14 +525,7 @@
       for (i = 0; i < 4; i++) {
          if ((partitions[i].firstLBA == start32) && (partitions[i].lengthLBA = length32) &&
              (partitions[i].partitionType != 0xEE)) {
-            partitions[i].firstLBA = UINT32_C(0);
-            partitions[i].lengthLBA = UINT32_C(0);
-            partitions[i].status = UINT8_C(0);
-            partitions[i].partitionType = UINT8_C(0);
-            for (j = 0; j < 3; j++) {
-               partitions[i].firstSector[j] = UINT8_C(0);
-               partitions[i].lastSector[j] = UINT8_C(0);
-            } // for j (CHS data blanking)
+            DeletePartition(i);
             OptimizeEESize();
             deleted = 1;
          } // if (match found)
@@ -594,7 +603,7 @@
 // setup to begin with....
 void MBRData::MakePart(int num, uint32_t start, uint32_t length, int type,
                        int bootable) {
-   
+
    partitions[num].status = (uint8_t) bootable * (uint8_t) 0x80;
    partitions[num].firstSector[0] = UINT8_C(0);
    partitions[num].firstSector[1] = UINT8_C(0);
@@ -657,7 +666,7 @@
 
 // Finds the first free sector on the disk from start backward.
 uint32_t MBRData::FindFirstInFree(uint32_t start) {
-   uint32_t nearestStart, bestLastLBA, thisLastLBA;
+   uint32_t bestLastLBA, thisLastLBA;
    int i;
 
    bestLastLBA = 1;
@@ -752,7 +761,7 @@
       // partitions (Note similar protection is in GPTData::XFormPartitions(),
       // but I want it here too in case I call this function in another
       // context in the future....)
-      if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) && 
+      if ((origType != 0x05) && (origType != 0x0f) && (origType != 0x85) &&
           (origType != 0x00) && (origType != 0xEE)) {
          firstSector = (uint64_t) origPart->firstLBA;
          newPart.SetFirstLBA(firstSector);
diff --git a/mbr.h b/mbr.h
index 3d1136b..ff824c5 100644
--- a/mbr.h
+++ b/mbr.h
@@ -105,6 +105,7 @@
    void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
                  int bootable = 0);
    int MakeBiggestPart(int i, int type); // Make partition filling most space
+   void DeletePartition(int i);
    int DeleteByLocation(uint64_t start64, uint64_t length64);
    void OptimizeEESize(void);
    void SetHybrid(void) {state = hybrid;} // Set hybrid flag
diff --git a/parttypes.cc b/parttypes.cc
index 7e5a2a3..5cdac0b 100644
--- a/parttypes.cc
+++ b/parttypes.cc
@@ -293,6 +293,14 @@
    int found = 0;
    struct GUIDData theGUID;
 
+   // Start by assigning a default GUID for the return value. Done
+   // "raw" to avoid the necessity for a recursive call and the
+   // remote possibility of an infinite recursive loop that this
+   // approach would present....
+   theGUID.data1 = UINT64_C(0x4433B9E5EBD0A0A2);
+   theGUID.data2 = UINT64_C(0xC79926B7B668C087);
+
+   // Now search the type list for a match to the ID....
    while ((theItem != NULL) && (!found)) {
       if (theItem->MBRType == ID)  { // found it!
          theGUID = theItem->GUIDType;
@@ -302,8 +310,7 @@
       } // if/else
    } // while
    if (!found) {
-      theGUID = IDToGUID(0x0700); // assign a default type code
-      printf("Exact type match not found for type code %lx; assigning type code for\n'Linux/Windows data'\n",
+      printf("Exact type match not found for type code %04X; assigning type code for\n'Linux/Windows data'\n",
              ID);
    } // if (!found)
    return theGUID;
@@ -317,7 +324,7 @@
 uint16_t PartTypes::GUIDToID(struct GUIDData typeCode) {
    AType* theItem = allTypes;
    int found = 0;
-   uint16_t theID;
+   uint16_t theID = 0xFFFF;
 
    while ((theItem != NULL) && (!found)) {
       if ((theItem->GUIDType.data1 == typeCode.data1) &&
diff --git a/parttypes.h b/parttypes.h
index 7c336a4..5a34d30 100644
--- a/parttypes.h
+++ b/parttypes.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <string>
+#include <string.h>
 #include "support.h"
 
 #ifndef __PARTITION_TYPES
diff --git a/support.cc b/support.cc
index 798aff8..e5b1860 100644
--- a/support.cc
+++ b/support.cc
@@ -15,6 +15,7 @@
 #include <stdint.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include "support.h"
 
 #include <sys/types.h>
@@ -184,8 +185,9 @@
    return theValue;
 } // BlocksToSI()
 
-// Returns block size of device pointed to by fd file descriptor, or -1
-// if there's a problem
+// Returns block size of device pointed to by fd file descriptor. If the ioctl
+// returns an error condition, print a warning but return a value of SECTOR_SIZE
+// (512)..
 int GetBlockSize(int fd) {
    int err, result;
 
@@ -199,13 +201,21 @@
 #endif
 #endif
 
+   if (err == -1) {
+      result = SECTOR_SIZE;
+      // ENOTTY = inappropriate ioctl; probably being called on a disk image
+      // file, so don't display the warning message....
+      if (errno != ENOTTY) {
+         printf("\aError %d when determining sector size! Setting sector size to %d\n",
+                errno, SECTOR_SIZE);
+      } // if
+   } // if
+
    if (result != 512) {
       printf("\aWARNING! Sector size is not 512 bytes! This program is likely to ");
       printf("misbehave!\nProceed at your own risk!\n\n");
    } // if
 
-   if (err == -1)
-      result = -1;
    return (result);
 } // GetBlockSize()
 
@@ -380,7 +390,37 @@
       fd = open(deviceFilename, O_WRONLY|O_SHLOCK);
    } // if
 #endif
-} // MyOpen()
+	return fd;
+} // OpenForWrite()
+
+// Resync disk caches so the OS uses the new partition table. This code varies
+// a lot from one OS to another.
+void DiskSync(int fd) {
+   int i;
+
+   sync();
+#ifdef __APPLE__
+   printf("Warning: The kernel may continue to use old or deleted partitions.\n"
+          "You should reboot or remove the drive.\n");
+	    /* don't know if this helps
+	     * it definitely will get things on disk though:
+            * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
+   i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
+#else
+#ifdef __FreeBSD__
+   sleep(2);
+   i = ioctl(fd, DIOCGFLUSH);
+   printf("Warning: The kernel may continue to use old or deleted partitions.\n"
+          "You should reboot or remove the drive.\n");
+#else
+   sleep(2);
+   i = ioctl(fd, BLKRRPART);
+   if (i)
+      printf("Warning: The kernel is still using the old partition table.\n"
+            "The new table will be used at the next reboot.\n");
+#endif
+#endif
+} // DiskSync()
 
 /**************************************************************************************
  *                                                                                    *
@@ -392,35 +432,62 @@
 // The disksize function is taken from the Linux fdisk code and modified
 // to work around a problem returning a uint64_t value on Mac OS.
 uint64_t disksize(int fd, int *err) {
-	long sz; // Do not delete; needed for Linux
-	long long b; // Do not delete; needed for Linux
-	uint64_t sectors;
+   long sz; // Do not delete; needed for Linux
+   long long b; // Do not delete; needed for Linux
+   uint64_t sectors = 0, bytes = 0; // size in sectors & bytes
+   struct stat st;
 
-	// Note to self: I recall testing a simplified version of
-	// this code, similar to what's in the __APPLE__ block,
-	// on Linux, but I had some problems. IIRC, it ran OK on 32-bit
-	// systems but not on 64-bit. Keep this in mind in case of
-	// 32/64-bit issues on MacOS....
+   // Note to self: I recall testing a simplified version of
+   // this code, similar to what's in the __APPLE__ block,
+   // on Linux, but I had some problems. IIRC, it ran OK on 32-bit
+   // systems but not on 64-bit. Keep this in mind in case of
+   // 32/64-bit issues on MacOS....
 #ifdef __APPLE__
-	*err = ioctl(fd, DKIOCGETBLOCKCOUNT, &sectors);
+   *err = ioctl(fd, DKIOCGETBLOCKCOUNT, &sectors);
 #else
 #ifdef __FreeBSD__
-        *err = ioctl(fd, DIOCGMEDIASIZE, &sz);
-        b = GetBlockSize(fd);
-        sectors = sz / b;
+   *err = ioctl(fd, DIOCGMEDIASIZE, &sz);
+   b = GetBlockSize(fd);
+   sectors = sz / b;
 #else
-	*err = ioctl(fd, BLKGETSIZE, &sz);
-	if (*err) {
-		sz = 0;
-		if (errno != EFBIG)
-			return sz;
-	}
-	*err = ioctl(fd, BLKGETSIZE64, &b);
-	if (*err || b == 0 || b == sz)
-		sectors = sz;
-	else
-		sectors = (b >> 9);
+   *err = ioctl(fd, BLKGETSIZE, &sz);
+   if (*err) {
+      sectors = sz = 0;
+   } // if
+   if ((errno == EFBIG) || (!*err)) {
+      *err = ioctl(fd, BLKGETSIZE64, &b);
+      if (*err || b == 0 || b == sz)
+         sectors = sz;
+      else
+         sectors = (b >> 9);
+   } // if
+
+//         if (*err) {
+//            sz = 0;
+//            if (errno != EFBIG)
+//               return sz;
+//         }
+//         *err = ioctl(fd, BLKGETSIZE64, &b);
+//         if (*err || b == 0 || b == sz)
+//            sectors = sz;
+//         else
+//            sectors = (b >> 9);
+
 #endif
 #endif
-	return sectors;
+
+   // The above methods have failed (or it's a bum filename reference),
+   // so let's assume it's a regular file (a QEMU image, dd backup, or
+   // what have you) and see what stat() gives us....
+   if (sectors == 0) {
+      if (fstat(fd, &st) == 0) {
+         bytes = (uint64_t) st.st_size;
+         if ((bytes % UINT64_C(512)) != 0)
+            fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!"
+                            " Misbehavior is likely!\n\a");
+         sectors = bytes / UINT64_C(512);
+      } // if
+   } // if
+//   printf("In disksize(), sectors is %lld.\n", sectors);
+   return sectors;
 }
diff --git a/support.h b/support.h
index 60fcb8c..d6e4f92 100644
--- a/support.h
+++ b/support.h
@@ -18,7 +18,7 @@
 #include <linux/fs.h>
 #endif
 
-#include <string>
+#include <string.h>
 
 #ifndef __GPTSUPPORT
 #define __GPTSUPPORT
@@ -62,6 +62,7 @@
 void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
 uint64_t PowerOf2(int value);
 int OpenForWrite(char* deviceFilename);
+void DiskSync(int fd); // resync disk caches to use new partitions
 
 uint64_t disksize(int fd, int* err);