aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG27
-rw-r--r--Makefile4
-rw-r--r--attributes.h2
-rw-r--r--bsd.cc1
-rw-r--r--gdisk.88
-rw-r--r--gdisk.cc11
-rw-r--r--gpt.cc68
-rw-r--r--gptpart.cc1
-rw-r--r--mbr.cc43
-rw-r--r--mbr.h1
-rw-r--r--parttypes.cc13
-rw-r--r--parttypes.h2
-rw-r--r--support.cc127
-rw-r--r--support.h3
14 files changed, 212 insertions, 99 deletions
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 @@ CC=gcc
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 @@ int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector)
// 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 @@ menu provides unusually dangerous or obscure options. These are:
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 @@ the main menu.
.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 @@ entering data. When only one option is possible,
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 main(int argc, char* argv[]) {
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 @@ int DoCommand(char* filename, struct GPTData* theGPT) {
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 @@ GPTData::~GPTData(void) {
// 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 @@ int GPTData::CheckHeaderValidity(void) {
} // 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 @@ int GPTData::CheckHeaderCRC(struct GPTHeader* header) {
// 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 @@ void GPTData::LoadSecondTableAsMain(void) {
// 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 @@ int GPTData::SaveGPTData(void) {
// 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 @@ void GPTData::ShowGPTState(void) {
// 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 @@ void GPTData::SetAttributes(uint32_t partNum) {
// 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 @@ int GPTData::DestroyGPT(void) {
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 GPTData::XFormPartitions(void) {
int i, numToConvert;
uint8_t origType;
struct newGUID;
- char name[NAME_SIZE];
// Clear out old data & prepare basics....
ClearGPTData();
@@ -1391,7 +1383,7 @@ int GPTData::XFormPartitions(void) {
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 @@ void GPTData::MakeHybrid(void) {
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 @@ void GPTData::MakeHybrid(void) {
(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 @@ void GPTData::SortGPT(void) {
// 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 @@ uint64_t GPTData::FindFirstAvailable(uint64_t start) {
// 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 @@ int GPTData::IsFree(uint64_t sector) {
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 @@ GPTPart & GPTPart::operator=(const GPTPart & orig) {
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 @@ void MBRData::ReadMBRData(int fd, int checkBlockSize) {
// 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 @@ void MBRData::WriteMBRData(int fd) {
} // for i...
// Now write that data structure...
+ lseek64(fd, 0, SEEK_SET);
write(fd, &tempMBR, 512);
/* write(fd, code, 440);
@@ -298,7 +300,7 @@ void MBRData::WriteMBRData(int fd) {
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 @@ int MBRData::MakeBiggestPart(int i, int type) {
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 @@ int MBRData::DeleteByLocation(uint64_t start64, uint64_t length64) {
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 @@ void MBRData::ShowState(void) {
// 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 @@ uint32_t MBRData::FindLastInFree(uint32_t start) {
// 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 @@ GPTPart MBRData::AsGPT(int i) {
// 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 @@ public:
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 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
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 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
} // 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 @@ struct GUIDData PartTypes::IDToGUID(uint16_t ID) {
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 @@ char* BytesToSI(uint64_t size, char theValue[]) {
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 @@ int GetBlockSize(int fd) {
#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 @@ int OpenForWrite(char* deviceFilename) {
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 @@ int OpenForWrite(char* deviceFilename) {
// 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;
-
- // 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....
+ 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....
#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 @@ int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-en
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);