diff options
-rw-r--r-- | CHANGELOG | 27 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | attributes.h | 2 | ||||
-rw-r--r-- | bsd.cc | 1 | ||||
-rw-r--r-- | gdisk.8 | 8 | ||||
-rw-r--r-- | gdisk.cc | 11 | ||||
-rw-r--r-- | gpt.cc | 68 | ||||
-rw-r--r-- | gptpart.cc | 1 | ||||
-rw-r--r-- | mbr.cc | 43 | ||||
-rw-r--r-- | mbr.h | 1 | ||||
-rw-r--r-- | parttypes.cc | 13 | ||||
-rw-r--r-- | parttypes.h | 2 | ||||
-rw-r--r-- | support.cc | 127 | ||||
-rw-r--r-- | support.h | 3 |
14 files changed, 212 insertions, 99 deletions
@@ -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: ------ @@ -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 @@ -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; @@ -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: @@ -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(); @@ -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 @@ -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, @@ -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); @@ -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 @@ -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, §ors); + *err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors); #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; } @@ -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); |