Updates for version 0.4.2
New feature: Ability to edit disk images. Several small bug fixes and feature enhancements (see CHANGELOG).
This commit is contained in:
27
CHANGELOG
27
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:
|
||||
------
|
||||
|
||||
|
||||
4
Makefile
4
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)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include "support.h"
|
||||
|
||||
#ifndef __GPT_ATTRIBUTES
|
||||
|
||||
1
bsd.cc
1
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;
|
||||
|
||||
8
gdisk.8
8
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:
|
||||
|
||||
|
||||
11
gdisk.cc
11
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();
|
||||
|
||||
68
gpt.cc
68
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
|
||||
|
||||
@@ -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,
|
||||
|
||||
43
mbr.cc
43
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);
|
||||
|
||||
1
mbr.h
1
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
|
||||
|
||||
13
parttypes.cc
13
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) &&
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include "support.h"
|
||||
|
||||
#ifndef __PARTITION_TYPES
|
||||
|
||||
125
support.cc
125
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;
|
||||
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, §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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user