Commit 1fa8d07e authored by Guillaume Delacour's avatar Guillaume Delacour

Imported Upstream version 0.6.14

parent 1d693aae
CC=gcc
CXX=g++
#CFLAGS=-O2 -fpack-struct
CFLAGS=-O2 -fpack-struct -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -fpack-struct -Wuninitialized -Wreturn-type -D_FILE_OFFSET_BITS=64 -g
LIB_NAMES=crc32 support gptpart mbr gpt bsd parttypes attributes
CFLAGS+=-D_FILE_OFFSET_BITS=64
CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64
LDFLAGS+=
LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
DEPEND= makedepend $(CFLAGS)
DEPEND= makedepend $(CXXFLAGS)
#$(APPNAME): $(MBR2GPT_OBJS)
# $(CC) $(MBR2GPT_OBJS) -o $@
all: gdisk sgdisk
gdisk: $(LIB_OBJS) gdisk.o
$(CXX) $(LIB_OBJS) gdisk.o -o gdisk
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
$(CXX) $(LIB_OBJS) gdisk.o gpttext.o $(LDFLAGS) -luuid -o gdisk
wipegpt: $(LIB_OBJS) wipegpt.o
$(CXX) $(LIB_OBJS) wipegpt.o -o wipegpt
sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o $(LDFLAGS) -luuid -lpopt -o sgdisk
lint: #no pre-reqs
lint $(SRCS)
clean: #no pre-reqs
rm -f core *.o *~ gdisk
rm -f core *.o *~ gdisk sgdisk
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
$(OBJS):
$(CRITICAL_CXX_FLAGS)
# DO NOT DELETE
CC=gcc
CXX=g++
CFLAGS+=-D_FILE_OFFSET_BITS=64
CXXFLAGS+=-Wall -D_FILE_OFFSET_BITS=64 -I/usr/local/include
LDFLAGS+=
LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
DEPEND= makedepend $(CXXFLAGS)
all: gdisk sgdisk
gdisk: $(LIB_OBJS) gdisk.o gpttext.o
$(CXX) $(LIB_OBJS) gdisk.o gpttext.o -L/usr/local/lib $(LDFLAGS) -luuid -o gdisk
sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -L/usr/local/lib $(LDFLAGS) -luuid -lpopt -o sgdisk
lint: #no pre-reqs
lint $(SRCS)
clean: #no pre-reqs
rm -f core *.o *~ gdisk sgdisk
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
$(OBJS):
$(CRITICAL_CXX_FLAGS)
# DO NOT DELETE
CC=gcc
CXX=g++
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
LIB_NAMES=crc32 support guid partnotes gptpart mbr gpt bsd parttypes attributes diskio diskio-unix
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
DEPEND= makedepend $(CFLAGS)
all: gdisk sgdisk
gdisk: $(LIB_OBJS) gpttext.o gdisk.o
$(CXX) $(LIB_OBJS) gpttext.o gdisk.o -o gdisk
sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -L/opt/local/lib -lpopt -o sgdisk
testguid: $(LIB_OBJS) testguid.o
$(CXX) $(LIB_OBJS) testguid.o -o testguid
lint: #no pre-reqs
lint $(SRCS)
clean: #no pre-reqs
rm -f core *.o *~ gdisk sgdisk
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
$(OBJS):
# DO NOT DELETE
CC=/usr/bin/i586-mingw32msvc-gcc
CXX=/usr/bin/i586-mingw32msvc-g++
STRIP=/usr/bin/i586-mingw32msvc-strip
CFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -g
CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -g
#CXXFLAGS=-O2 -Wall -D_FILE_OFFSET_BITS=64 -I /usr/local/include -I/opt/local/include -g
LIB_NAMES=guid gptpart partnotes bsd parttypes attributes crc32 mbr gpt support diskio diskio-windows
LIB_SRCS=$(NAMES:=.cc)
LIB_OBJS=$(LIB_NAMES:=.o)
LIB_HEADERS=$(LIB_NAMES:=.h)
DEPEND= makedepend $(CFLAGS)
all: gdisk
gdisk: $(LIB_OBJS) gpttext.o gdisk.o
$(CXX) $(LIB_OBJS) gpttext.o gdisk.o -luuid -o gdisk.exe
sgdisk: $(LIB_OBJS) sgdisk.o
$(CXX) $(LIB_OBJS) sgdisk.o -lpopt -o sgdisk.exe
lint: #no pre-reqs
lint $(SRCS)
clean: #no pre-reqs
rm -f core *.o *~ gdisk.exe sgdisk.exe
strip: #no pre-reqs
$(STRIP) gdisk.exe
# what are the source dependencies
depend: $(SRCS)
$(DEPEND) $(SRCS)
$(OBJS):
# DO NOT DELETE
This diff is collapsed.
......@@ -7,8 +7,8 @@ Introduction
This software is intended as a (somewhat) fdisk-workalike program for
GPT-partitioned disks. Although libparted and programs that use it (GNU
Parted, gparted, etc.) provide the ability to handle GPT disks, they have
certain limitations that gdisk overcomes. Specific advantages of gdisk
include:
certain limitations that gdisk overcomes. Specific advantages of gdisk and
sgdisk include:
* The ability to convert MBR-partitioned disks in-place to GPT format,
without losing data
......@@ -25,7 +25,7 @@ include:
disk
* A user interface that's familiar to long-time users of Linux
fdisk
fdisk (gdisk only)
* The MBR boot loader code is left alone (GNU Parted tends to
wipe it out with every change)
......@@ -33,43 +33,71 @@ include:
* The ability to create a hybrid MBR, which permits GPT-unaware
OSes to access up to three GPT partitions on the disk
Of course, gdisk isn't without its limitations. Most notably, it lacks the
filesystem awareness and filesystem-related features of GNU Parted. You
Of course, GPT fdisk isn't without its limitations. Most notably, it lacks
the filesystem awareness and filesystem-related features of GNU Parted. You
can't resize a partition's filesystem or create a partition with a
filesystem already in place with gdisk, for instance. There's no GUI
version of gdisk.
The GPT fdisk package provides two program files: the interactive text-mode
gdisk and the command-line-driven sgdisk. The former is intended for use in
manually partitioning disks or changing partitioning details; the latter is
intended for use in scripts to help automate tasks such as disk cloning or
preparing multiple disks for Linux installation.
Installing
----------
To compile gdisk, you must have appropriate development tools installed,
most notably the GNU Compiler Collection (GCC) and its g++ compiler for
C++. Uncompress the package and type "make" at the command prompt in the
resulting directory. The result should be a program file called gdisk. You
can use this in place or copy the file to a suitable directory, such as
/usr/local/sbin. You can copy the man page (gdisk.8) to /usr/local/man/man8
to make it available.
To compile GPT fdisk, you must have appropriate development tools
installed, most notably the GNU Compiler Collection (GCC) and its g++
compiler for C++. In addition, note these requirements:
* On Linux, FreeBSD, and OS X, libuuid must be installed. This is the
standard for Linux and OS X, although you may need to install a package
called uuid-dev or something similar to get the headers. On FreeBSD, the
e2fsprogs-libuuid port must be installed.
* The sgdisk program also requires the popt library and its development
files (headers). Most Linux distributions install popt by default, but
you may need to install a package called popt-dev, popt-devel, or
something similar to obtain the header files. Mac OS users can find a
version of popt for Mac OS from http://popt.darwinports.com; however,
you'll first need to install DarwinPorts (instructions exist on the
preceding page). Alternatively, you can compile gdisk alone, without
sgdisk; gdisk doesn't require popt.
When all the necessary development tools and libraries are installed, you
can uncompress the package and type "make" at the command prompt in the
resulting directory. (You may need to type "make -f Makefile.mac" on Mac OS
X, "make -f Makefile.freebsd" on FreeBSD, or "make -f Makefile.mingw" to
compile using MinGW for Windows.) You may also need to add header (include)
directories or library directories by setting the CXXFLAGS environment
variable or by editing the Makefile. The result should be program files
called gdisk and sgdisk. Typing "make gdisk" or "make sgdisk" will compile
only the requested programs. You can use these programs in place or copy
the files to a suitable directory, such as /usr/local/sbin. You can copy
the man pages (gdisk.8 and sgdisk.8) to /usr/local/man/man8 to make them
available.
Caveats
-------
THIS SOFTWARE IS EARLY BETA SOFTWARE! IF IT WIPES OUT YOUR HARD DISK OR
EATS YOUR CAT, DON'T BLAME ME! To date, I've tested the software mainly on
two USB flash drives, 2 GiB and 8 GiB in size. I've also made a few minor
tweaks to a production system with a 500 GiB hard disk and made more
extensive changes to a handful of 80-160 GiB hard disks. I believe all
data-corruption bugs to be squashed, but I know full well that the odds of
my missing something are high. This is particularly true for large drives;
I have no way of testing the software with > 2TiB drives, which will test
the 64-bit sector pointer support. I've received user reports of success
with >2TiB drives, though.
THIS SOFTWARE IS BETA SOFTWARE! IF IT WIPES OUT YOUR HARD DISK OR EATS YOUR
CAT, DON'T BLAME ME! To date, I've tested the software on several USB flash
drives, a handful of PATA and SATA hard disks, and several virtual disks in
a QEMU environment. I believe all data-corruption bugs to be squashed, but
I know full well that the odds of my missing something are high. This is
particularly true for large drives; my only direct testing with such disks
is with virtual QEMU disks. I've received user reports of success with
RAID arrays over 2TiB in size, though.
My main development platform is a system running the 64-bit version of
Ubuntu 8.04. I've also tested on 64-bit OpenSuSE, 32-bit Fedora 10, 32-bit
Ubuntu 6.10, 64-bit Gentoo, 32-bit PowerPC Linux, 32-bit Intel-based Mac
OS X, and 64-bit Fedora 7.1. Problems relating to 64-bit integers on the
32-bit Linux have been common during development and may crop up in the
future. The Mac OS X, FreeBSD, and big-endian (PowerPC) support are new.
Gentoo Linux (previously Ubuntu 8.04). I've also tested on 64-bit OpenSuSE,
32-bit Fedora 10, 32-bit Fedora 11, 32-bit Ubuntu 6.10, 64-bit Ubunut 9.10,
32-bit PowerPC Debian Linux, 32-bit Intel-based Mac OS X 10.5 and 10.6,
64-bit FreeBSD 7.1, and Windows 7. Problems relating to 64-bit integers on
the 32-bit Linux have been common during development and may crop up in the
future.
Redistribution
--------------
......@@ -86,8 +114,8 @@ other GPLed programs:
Krzysztof Dabrowski and ElysiuM deeZine. (See the crc32.h and
crc32.cc source code files.)
- A function to find the disk size is taken from Linux fdisk by
A. V. Le Blanc.
- A function to find the disk size is taken from Linux fdisk by A. V. Le
Blanc. This code has subsequently been heavily modified.
Additional code contributors include:
......
......@@ -8,77 +8,218 @@
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include "attributes.h"
#include "support.h"
using namespace std;
// Constructor. Its main task is to initialize the attribute name
// data.
string Attributes::atNames[NUM_ATR];
int Attributes::numAttrs = 0;
//Attributes::staticInit Attributes::staticInitializer;
// Default constructor
Attributes::Attributes(void) {
int i;
char temp[ATR_NAME_SIZE];
numAttrs++;
if (numAttrs == 1)
Setup();
attributes = 0;
} // constructor
// Alternate constructor
Attributes::Attributes(const uint64_t a) {
numAttrs++;
if (numAttrs == 1)
Setup();
attributes = a;
} // alternate constructor
// Destructor.
Attributes::~Attributes(void) {
numAttrs--;
} // Attributes destructor
void Attributes::Setup(void) {
ostringstream temp;
// Most bits are undefined, so start by giving them an
// appropriate name
for (i = 1; i < NUM_ATR; i++) {
sprintf(temp, "Undefined bit #%d", i);
strcpy(atNames[i], temp);
for (int i = 0; i < NUM_ATR; i++) {
temp.str("");
temp << "Undefined bit #" << i;
Attributes::atNames[i] = temp.str();
} // for
// Now reset those names that are defined....
strcpy(atNames[0], "system partition");
strcpy(atNames[60], "read-only");
strcpy(atNames[62], "hidden");
strcpy(atNames[63], "do not automount");
} // Attributes constructor
// Destructor.
Attributes::~Attributes(void) {
} // Attributes destructor
atNames[0] = "system partition"; // required for computer to operate
atNames[1] = "hide from EFI";
atNames[2] = "legacy BIOS bootable";
atNames[60] = "read-only";
atNames[62] = "hidden";
atNames[63] = "do not automount";
} // Attributes::Setup()
// Display current attributes to user
void Attributes::DisplayAttributes(void) {
int i;
uint32_t i;
int numSet = 0;
printf("Attribute value is %llX. Set fields are:\n",
(unsigned long long) attributes);
cout << "Attribute value is ";
cout.setf(ios::uppercase);
cout.fill('0');
cout.width(16);
cout << hex << attributes << dec << ". Set fields are:\n";
for (i = 0; i < NUM_ATR; i++) {
if (((attributes >> i) % 2) == 1) { // bit is set
/* if (strncmp("Undefined", atNames[i], 9) != 0)
printf("%s\n", atNames[i]); */
if (strncmp("Undefined", atNames[NUM_ATR - i - 1], 9) != 0)
printf("%s\n", atNames[NUM_ATR - i - 1]);
if ((UINT64_C(1) << i) & attributes) {
cout << i << " (" << GetAttributeName(i) << ")" << "\n";
numSet++;
} // if
} // for
cout.fill(' ');
if (numSet == 0)
cout << " No fields set\n";
cout << "\n";
} // Attributes::DisplayAttributes()
// Display attributes for a partition. Note that partNum is just passed for
// immediate display; it's not used to access a particular partition.
void Attributes::ShowAttributes(const uint32_t partNum) {
uint32_t bitNum;
bool bitset;
for (bitNum = 0; bitNum < 64; bitNum++) {
bitset = (UINT64_C(1) << bitNum) & attributes;
if (bitset) {
cout << partNum+1 << ":" << bitNum << ":" << bitset
<< " (" << GetAttributeName(bitNum) << ")" << endl;
} // if
} // for
} // Attributes::ShowAttributes
// Prompt user for attribute changes
void Attributes::ChangeAttributes(void) {
int response, i;
int response;
uint64_t bitValue;
printf("Known attributes are:\n");
for (i = 0; i < NUM_ATR; i++) {
if (strncmp("Undefined", atNames[i], 9) != 0)
printf("%d - %s\n", i, atNames[i]);
} // for
cout << "Known attributes are:\n";
ListAttributes();
cout << "\n";
do {
response = GetNumber(0, 64, -1, "Toggle which attribute field (0-63, 64 to exit): ");
DisplayAttributes();
response = GetNumber(0, NUM_ATR, 64,
"Toggle which attribute field (0-63, 64 or <Enter> to exit): ");
if (response != 64) {
bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit
// bitValue = PowerOf2(response); // Find the integer value of the bit
if ((bitValue & attributes) == bitValue) { // bit is set
attributes -= bitValue; // so unset it
printf("Have disabled the '%s' attribute.\n", atNames[response]);
bitValue = UINT64_C(1) << response; // Find the integer value of the bit
if (bitValue & attributes) { // bit is set
attributes &= ~bitValue; // so unset it
cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
} else { // bit is not set
attributes += bitValue; // so set it
printf("Have enabled the '%s' attribute.\n", atNames[response]);
attributes |= bitValue; // so set it
cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
} // if/else
} // if
} while (response != 64);
} // Attributes::ChangeAttributes()
// Display all defined attributes on the screen (omits undefined bits).
void Attributes::ListAttributes(void) {
uint32_t bitNum;
string tempAttr;
for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
tempAttr = GetAttributeName(bitNum);
if (tempAttr.substr(0, 15) != "Undefined bit #" )
cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
} // for
} // Attributes::ListAttributes
// multifaceted attributes access
// returns true upon success, false upon failure
bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
// attribute access opcode
typedef enum {
ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask)
ao_unknown, // must be after bitmask operators and before bitnum operators
ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum)
} attribute_opcode_t; // typedef enum
// translate attribute operator into an attribute opcode
attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
if (attributeOperator == "or") attributeOpcode = ao_or;
else if (attributeOperator == "nand") attributeOpcode = ao_nand;
else if (attributeOperator == "xor") attributeOpcode = ao_xor;
else if (attributeOperator == "=") attributeOpcode = ao_assignall;
else if (attributeOperator == "set") attributeOpcode = ao_set;
else if (attributeOperator == "clear") attributeOpcode = ao_clear;
else if (attributeOperator == "toggle") attributeOpcode = ao_toggle;
else if (attributeOperator == "get") attributeOpcode = ao_get;
else {
cerr << "Unknown attributes operator: " << attributeOperator << endl;
return false;
} // else
} // attributeOpcode
// get bit mask if operating on entire attribute set
uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
cerr << "Could not convert hex attribute mask" << endl;
return false;
} // if
}} // attributeBitMask, if
// get bit number and calculate bit mask if operating on a single attribute
int bitNum; { if (attributeOpcode > ao_unknown) {
if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
cerr << "Could not convert bit number" << endl;
return false;
} // if
const uint64_t one = 1;
attributeBitMask = one << bitNum;
}} // bitNum, if
switch (attributeOpcode) {
// assign all attributes at once
case ao_assignall: attributes = attributeBitMask; break;
// set individual attribute(s)
case ao_set:
case ao_or: attributes |= attributeBitMask; break;
// clear individual attribute(s)
case ao_clear:
case ao_nand: attributes &= ~attributeBitMask; break;
// toggle individual attribute(s)
case ao_toggle:
case ao_xor: attributes ^= attributeBitMask; break;
// display a single attribute
case ao_get: {
cout << partNum+1 << ":" << bitNum << ":"
<< bool (attributeBitMask & attributes) << endl;
break;
} // case ao_get
default: break; // will never get here
} // switch
return true;
} // Attributes::OperateOnAttributes()
/*******************************
* *
* Non-class support functions *
* *
*******************************/
// Display attributes
ostream & operator<<(ostream & os, const Attributes & data) {
os << data.GetAttributes();
return os;
} // operator<<()
\ No newline at end of file
......@@ -2,10 +2,7 @@
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "support.h"
#include <string>
#ifndef __GPT_ATTRIBUTES
#define __GPT_ATTRIBUTES
......@@ -17,15 +14,28 @@ using namespace std;
class Attributes {
protected:
static string atNames[NUM_ATR];
static int numAttrs;
void Setup(void);
uint64_t attributes;
char atNames[NUM_ATR][ATR_NAME_SIZE];
public:
Attributes(void);
Attributes(const uint64_t a);
~Attributes(void);
void SetAttributes(uint64_t a) {attributes = a;}
uint64_t GetAttributes(void) {return attributes;}
void operator=(uint64_t a) {attributes = a;}
uint64_t GetAttributes(void) const {return attributes;}
void DisplayAttributes(void);
void ShowAttributes(const uint32_t partNum);
void ChangeAttributes(void);
bool OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits);
static const string& GetAttributeName(const uint32_t bitNum) {return atNames [bitNum];}
static void ListAttributes(void);
}; // class Attributes
ostream & operator<<(ostream & os, const Attributes & data);
#endif
......@@ -10,13 +10,14 @@
#define __STDC_CONSTANT_MACROS
#include <stdio.h>
#include <unistd.h>
//#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <iostream>
#include <string>
#include "support.h"
#include "bsd.h"
......@@ -36,89 +37,96 @@ BSDData::BSDData(void) {
} // default constructor
BSDData::~BSDData(void) {
free(partitions);
if (partitions != NULL)
delete[] partitions;
} // destructor
// Read BSD disklabel data from the specified device filename. This function
// just opens the device file and then calls an overloaded function to do
// the bulk of the work.
int BSDData::ReadBSDData(char* device, uint64_t startSector, uint64_t endSector) {
int fd, allOK = 1;
if (device != NULL) {
if ((fd = open(device, O_RDONLY)) != -1) {
ReadBSDData(fd, startSector, endSector);
// the bulk of the work. Returns 1 on success, 0 on failure.
int BSDData::ReadBSDData(const string & device, uint64_t startSector, uint64_t endSector) {
int allOK = 1;
DiskIO myDisk;
if (device != "") {
if (myDisk.OpenForRead(device)) {
allOK = ReadBSDData(&myDisk, startSector, endSector);
} else {
allOK = 0;
} // if/else
close(fd);
myDisk.Close();
} else {
allOK = 0;
} // if/else
return allOK;
} // BSDData::ReadBSDData() (device filename version)
// Load the BSD disklabel data from an already-opened disk
// 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
int i, err, foundSig = 0, bigEnd = 0;
int BSDData::ReadBSDData(DiskIO *theDisk, uint64_t startSector, uint64_t endSector) {
int allOK = 1;
int i, foundSig = 0, bigEnd = 0;
int relative = 0; // assume absolute partition sector numbering
uint8_t buffer[4096]; // I/O buffer
uint32_t realSig;
uint32_t* temp32;
uint16_t* temp16;
BSDRecord* tempRecords;
int offset[NUM_OFFSETS] = { LABEL_OFFSET1, LABEL_OFFSET2 };
labelFirstLBA = startSector;
labelLastLBA = endSector;
offset[1] = theDisk->GetBlockSize();
// Read two sectors into memory; we'll extract data from
// this buffer. (Done to work around FreeBSD limitation)
lseek64(fd, startSector * 512, SEEK_SET);
err = read(fd, buffer, 2048);
// Read 4096 bytes (eight 512-byte sectors or equivalent)
// into memory; we'll extract data from this buffer.
// (Done to work around FreeBSD limitation on size of reads
// from block devices.)
allOK = theDisk->Seek(startSector);
if (allOK) allOK = theDisk->Read(buffer, 4096);
// Do some strangeness to support big-endian architectures...
bigEnd = (IsLittleEndian() == 0);
realSig = BSD_SIGNATURE;
if (bigEnd)
if (bigEnd && allOK)
ReverseBytes(&realSig, 4);
// Look for the signature at one of two locations
labelStart = LABEL_OFFSET1;
temp32 = (uint32_t*) &buffer[labelStart];
signature = *temp32;
if (signature == realSig) {
temp32 = (uint32_t*) &buffer[labelStart + 132];
signature2 = *temp32;
if (signature2 == realSig)
foundSig = 1;
} // if/else
if (!foundSig) { // look in second location
labelStart = LABEL_OFFSET2;
temp32 = (uint32_t*) &buffer[labelStart];
signature = *temp32;
if (signature == realSig) {
temp32 = (uint32_t*) &buffer[labelStart + 132];
signature2 = *temp32;
if (signature2 == realSig)
foundSig = 1;
} // if/else
// Look for the signature at any of two locations.
// Note that the signature is repeated at both the original
// offset and 132 bytes later, so we need two checks....
if (allOK) {
i = 0;
do {
temp32 = (uint32_t*) &buffer[offset[i]];
signature = *temp32;
if (signature == realSig) { // found first, look for second
temp32 = (uint32_t*) &buffer[offset[i] + 132];
signature2 = *temp32;
if (signature2 == realSig) {
foundSig = 1;
labelStart = offset[i];
} // if found signature
} // if/else
i++;
} while ((!foundSig) && (i < NUM_OFFSETS));
allOK = foundSig;
} // if
// Load partition metadata from the buffer....
temp32 = (uint32_t*) &buffer[labelStart + 40];
sectorSize = *temp32;
temp16 = (uint16_t*) &buffer[labelStart + 138];
numParts = *temp16;
if (allOK) {
temp32 = (uint32_t*) &buffer[labelStart + 40];
sectorSize = *temp32;
temp16 = (uint16_t*) &buffer[labelStart + 138];
numParts = *temp16;
} // if
// Make it big-endian-aware....
if (IsLittleEndian() == 0)
if ((IsLittleEndian() == 0) && allOK)
ReverseMetaBytes();
// Check validity of the data and flag it appropriately....
if (foundSig && (numParts <= MAX_BSD_PARTS)) {