New release: 0.4.0
This version adds support for FreeBSD and big-endian systems. It also adds support for BSD disklabels and an assortment of other changes, improvements, and bug fixes.
This commit is contained in:
28
CHANGELOG
28
CHANGELOG
@@ -1,6 +1,34 @@
|
||||
0.4.0:
|
||||
------
|
||||
|
||||
- Added support for BSD disklabels. The program can now convert disks that
|
||||
use "raw" disklabels, with the caveat that the first partition will
|
||||
almost certainly need to be deleted because it'll overlap the main GPT
|
||||
header; and convert disklabels contained within a GPT (or a former MBR,
|
||||
converted to GPT) partition. In the latter case, the 'b' main menu option
|
||||
is used.
|
||||
|
||||
- Added support for compiling on FreeBSD.
|
||||
|
||||
- Fixed bug that could cause crashes or incomplete sorts when sorting
|
||||
the partition table.
|
||||
|
||||
- New partitions, including converted ones, now take on the name of the
|
||||
partition type as a default name.
|
||||
|
||||
- Reorganized some code; created a separate C++ class for GPT partitions
|
||||
(GPTPart), which replaced a struct and enabled moving code from the
|
||||
bloated GPTData class into GPTPart.
|
||||
|
||||
- Fixed a bug that produced spurious warnings about unknown sector sizes
|
||||
when loading a backup file.
|
||||
|
||||
0.3.5:
|
||||
------
|
||||
|
||||
Note: This version was not officially publicly released; I wanted to test
|
||||
the big-endian support while developing 0.4.0.
|
||||
|
||||
- Tweaked the disk type identification code to warn users to re-sync their
|
||||
hybrid MBRs when one is detected.
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@ 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 mbr gpt parttypes attributes
|
||||
LIB_NAMES=support crc32 gptpart mbr gpt bsd parttypes attributes
|
||||
LIB_SRCS=$(NAMES:=.cc)
|
||||
LIB_OBJS=$(LIB_NAMES:=.o)
|
||||
LIB_HEADERS=$(LIB_NAMES:=.h)
|
||||
|
||||
14
README
14
README
@@ -13,6 +13,9 @@ include:
|
||||
* The ability to convert MBR-partitioned disks in-place to GPT format,
|
||||
without losing data
|
||||
|
||||
* The ability to convert BSD disklabels in-place to create GPT
|
||||
partitions, without losing data
|
||||
|
||||
* The ability to specify sector-exact partition sizes
|
||||
|
||||
* More flexible specification of filesystem type code GUIDs, which
|
||||
@@ -27,6 +30,9 @@ include:
|
||||
* The MBR boot loader code is left alone (GNU Parted tends to
|
||||
wipe it out with every change)
|
||||
|
||||
* 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
|
||||
can't resize a partition's filesystem or create a partition with a
|
||||
@@ -60,10 +66,10 @@ with >2TiB drives, 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, and 32-bit Intel-based
|
||||
Mac OS X. 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 and big-endian (PowerPC) support is new.
|
||||
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.
|
||||
|
||||
Redistribution
|
||||
--------------
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// Class to manage partition attribute codes. These are binary bit fields,
|
||||
// of which only three are currently (2/2009) documented on Wikipedia.
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
1
crc32.cc
1
crc32.cc
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
|
||||
* so make sure, you call it before using the other
|
||||
|
||||
47
gdisk.8
47
gdisk.8
@@ -1,13 +1,15 @@
|
||||
.\" Copyright 2009 Roderick W. Smith (rodsmith@rodsbooks.com)
|
||||
.\" May be distributed under the GNU General Public License
|
||||
.TH GDISK 8 "August 2009" "Linux 2.6" "GPT fdisk Manual"
|
||||
.TH GDISK 8 "August 2009" "0.4.0" "GPT fdisk Manual"
|
||||
.SH NAME
|
||||
gdisk \- GPT partition table manipulator for Linux
|
||||
gdisk \- GPT partition table manipulator for Linux and Unix
|
||||
.SH SYNOPSIS
|
||||
.BI "gdisk "
|
||||
[ \-l ]
|
||||
.I device
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Hard disks can be divided into one or more segments, known as
|
||||
.IR partitions .
|
||||
This division is described in the
|
||||
@@ -110,7 +112,7 @@ program employs a user interface similar to that of Linux's
|
||||
but
|
||||
.B "gdisk"
|
||||
modifies GPT partitions. It also has the capability of transforming MBR
|
||||
partitions into GPT partitions. Like the original
|
||||
partitions or BSD disklabels into GPT partitions. Like the original
|
||||
.B fdisk
|
||||
program,
|
||||
.B gdisk
|
||||
@@ -120,8 +122,9 @@ save your partitions.
|
||||
|
||||
.B gdisk
|
||||
is a text-mode menu-driven program for creation and manipulation of
|
||||
partition tables. It will automatically convert an MBR partition table to
|
||||
GPT format, or will load a GPT partition table. When used with the
|
||||
partition tables. It will automatically convert an MBR partition table or
|
||||
BSD disklabel stored without an MBR carrier partition to GPT format, or
|
||||
will load a GPT partition table. When used with the
|
||||
.IR "\-l"
|
||||
command-line option, the program displays the current partition table and
|
||||
then exits.
|
||||
@@ -173,6 +176,13 @@ will note that
|
||||
.B "gdisk"
|
||||
lacks the options and limitations associated with CHS geometries.
|
||||
|
||||
For best results, you should always use an OS-specific partition table
|
||||
program. For example, you should make Mac OS X partitions with the Mac OS
|
||||
X Disk Utility
|
||||
program and Linux partitions with the Linux
|
||||
.B "gdisk"
|
||||
or GNU Parted program.
|
||||
|
||||
Upon start,
|
||||
.B gdisk
|
||||
attempts to identify the partition type in use on the specified disk. If it
|
||||
@@ -180,10 +190,14 @@ finds valid GPT data,
|
||||
.B gdisk
|
||||
will use it. If
|
||||
.B gdisk
|
||||
finds a valid MBR but no GPT data, it will attempt to convert the MBR into
|
||||
GPT form. Upon exiting with the 'w' option,
|
||||
finds a valid MBR or BSD disklabel but no GPT data, it will attempt to
|
||||
convert the MBR or disklabel into GPT form. (BSD disklabels are likely to
|
||||
have unusable first and/or final partitions because they overlap with the
|
||||
GPT data structures, though.) GPT fdisk can identify, but not use data in,
|
||||
Apple Partition Map (APM) disks, which are used on 680x0- and PowerPC-based
|
||||
Macintoshes. Upon exiting with the 'w' option,
|
||||
.B gdisk
|
||||
will then replace the MBR with a GPT.
|
||||
will then replace the MBR or disklabel with a GPT.
|
||||
.IR "This action is potentially dangerous!"
|
||||
Your system may become unbootable, and partition type codes may become
|
||||
corrupted if the disk uses unrecognized type codes. Boot problems are
|
||||
@@ -257,13 +271,26 @@ Most interactions with
|
||||
occur with its interactive text-mode menus. The main menu provides the
|
||||
following options:
|
||||
|
||||
.TP
|
||||
.B b
|
||||
Convert BSD partitions into GPT partitions. This option works on BSD
|
||||
disklabels held within GPT (or converted MBR) partitions. Converted
|
||||
partitions' type codes are likely to need manual adjustment.
|
||||
.B gdisk
|
||||
will attempt to convert BSD disklabels stored on the main disk when
|
||||
launched, but this conversion is likely to produce first and/or last
|
||||
partitions that are unusable. The many BSD variants means that the
|
||||
probability of GPT fdisk being unable to convert a BSD disklabel are high
|
||||
compared to the likelihood of problems with an MBR conversion.
|
||||
|
||||
.TP
|
||||
.B c
|
||||
Change the GPT name of a partition. This name is encoded as a UTF-16
|
||||
string, but
|
||||
.B gdisk
|
||||
supports only ASCII characters as names. For the most part, Linux ignores
|
||||
the partition name, but it may be important in some OSes.
|
||||
the partition name, but it may be important in some OSes. GPT fdisk sets
|
||||
a default name based on the partition type code.
|
||||
|
||||
.TP
|
||||
.B d
|
||||
@@ -342,7 +369,7 @@ Sort partition entries. GPT partition numbers need not match the order of
|
||||
partitions on the disk. If you want them to match, you can use this option.
|
||||
Note that some partitioning utilities, such as GNU Parted, will sort
|
||||
partitions whenever they make changes. Such changes will be reflected in
|
||||
your Linux device filenames, so you may need to edit
|
||||
your device filenames, so you may need to edit
|
||||
.IR "/etc/fstab"
|
||||
if you use this option.
|
||||
|
||||
|
||||
12
gdisk.cc
12
gdisk.cc
@@ -4,6 +4,9 @@
|
||||
//
|
||||
// by Rod Smith, February 2009
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
//#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -24,7 +27,7 @@ int main(int argc, char* argv[]) {
|
||||
int doMore = 1;
|
||||
char* device = NULL;
|
||||
|
||||
printf("GPT fdisk (gdisk) version 0.3.5\n\n");
|
||||
printf("GPT fdisk (gdisk) version 0.4.0\n\n");
|
||||
|
||||
if (argc == 2) { // basic usage
|
||||
if (SizesOK()) {
|
||||
@@ -65,9 +68,9 @@ int DoCommand(char* filename, struct GPTData* theGPT) {
|
||||
fgets(line, 255, stdin);
|
||||
sscanf(line, "%c", &command);
|
||||
switch (command) {
|
||||
/* case 'b': case 'B':
|
||||
GetGUID();
|
||||
break; */
|
||||
case 'b': case 'B':
|
||||
theGPT->XFormDisklabel();
|
||||
break;
|
||||
case 'c': case 'C':
|
||||
if (theGPT->GetPartRange(&temp1, &temp2) > 0)
|
||||
theGPT->SetName(theGPT->GetPartNum());
|
||||
@@ -125,6 +128,7 @@ int DoCommand(char* filename, struct GPTData* theGPT) {
|
||||
} // DoCommand()
|
||||
|
||||
void ShowCommands(void) {
|
||||
printf("b\tconvert BSD disklabel partitions\n");
|
||||
printf("c\tchange a partition's name\n");
|
||||
printf("d\tdelete a partition\n");
|
||||
printf("i\tshow detailed information on a partition\n");
|
||||
|
||||
49
gpt.h
49
gpt.h
@@ -1,34 +1,21 @@
|
||||
/* gpt.h -- GPT and data structure definitions, types, and
|
||||
functions */
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "support.h"
|
||||
#include "parttypes.h"
|
||||
#include "mbr.h"
|
||||
#include "bsd.h"
|
||||
#include "gptpart.h"
|
||||
|
||||
#ifndef __GPTSTRUCTS
|
||||
#define __GPTSTRUCTS
|
||||
|
||||
#define GPT_SIGNATURE UINT64_C(0x5452415020494645)
|
||||
// Signatures for Apple (APM) disks, multiplied by 0x100000000
|
||||
#define APM_SIGNATURE1 UINT64_C(0x00004D5000000000)
|
||||
#define APM_SIGNATURE2 UINT64_C(0x0000535400000000)
|
||||
|
||||
/* Number and size of GPT entries... */
|
||||
#define NUM_GPT_ENTRIES 128
|
||||
#define GPT_SIZE 128
|
||||
/* Offset, in 512-byte sectors, for GPT table and partition data.
|
||||
Note this is above two multiplied together, divided by 512, with 2
|
||||
added
|
||||
#define GPT_OFFSET (((NUM_GPT_ENTRIES * GPT_SIZE) / SECTOR_SIZE) + 2)
|
||||
*/
|
||||
|
||||
#define HEADER_SIZE 92
|
||||
|
||||
#define GPT_RESERVED 420
|
||||
#define NAME_SIZE 72
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -42,7 +29,7 @@ using namespace std;
|
||||
enum GPTValidity {gpt_valid, gpt_corrupt, gpt_invalid};
|
||||
|
||||
// Which set of partition data to use
|
||||
enum WhichToUse {use_gpt, use_mbr, use_new};
|
||||
enum WhichToUse {use_gpt, use_mbr, use_bsd, use_new};
|
||||
|
||||
// Header (first 512 bytes) of GPT table
|
||||
struct GPTHeader {
|
||||
@@ -63,20 +50,11 @@ struct GPTHeader {
|
||||
unsigned char reserved2[GPT_RESERVED];
|
||||
}; // struct GPTHeader
|
||||
|
||||
struct GPTPartition {
|
||||
struct GUIDData partitionType;
|
||||
struct GUIDData uniqueGUID;
|
||||
uint64_t firstLBA;
|
||||
uint64_t lastLBA;
|
||||
uint64_t attributes;
|
||||
unsigned char name[NAME_SIZE];
|
||||
}; // struct GPTPartition
|
||||
|
||||
// Data in GPT format
|
||||
class GPTData {
|
||||
protected:
|
||||
struct GPTHeader mainHeader;
|
||||
struct GPTPartition *partitions;
|
||||
struct GPTPart *partitions;
|
||||
struct GPTHeader secondHeader;
|
||||
MBRData protectiveMBR;
|
||||
char device[256]; // device filename
|
||||
@@ -87,6 +65,8 @@ protected:
|
||||
int secondCrcOk;
|
||||
int mainPartsCrcOk;
|
||||
int secondPartsCrcOk;
|
||||
int apmFound; // set to 1 if APM detected
|
||||
int bsdFound; // set to 1 if BSD disklabel detected in MBR
|
||||
// uint32_t units; // display units, in multiples of sectors
|
||||
PartTypes typeHelper;
|
||||
public:
|
||||
@@ -95,6 +75,9 @@ public:
|
||||
~GPTData(void);
|
||||
int SetGPTSize(uint32_t numEntries);
|
||||
int CheckGPTSize(void);
|
||||
void ShowAPMState(void);
|
||||
void ShowGPTState(void);
|
||||
void PartitionScan(int fd);
|
||||
int LoadPartitions(char* deviceFilename);
|
||||
int ForceLoadGPTData(int fd);
|
||||
int LoadMainTable(void);
|
||||
@@ -112,7 +95,9 @@ public:
|
||||
uint64_t FindLastAvailable(uint64_t start);
|
||||
uint64_t FindLastInFree(uint64_t start);
|
||||
int IsFree(uint64_t sector);
|
||||
int XFormPartitions(MBRData* origParts);
|
||||
int XFormPartitions(void);
|
||||
int XFormDisklabel(int OnGptPart = -1);
|
||||
int XFormDisklabel(BSDData* disklabel, int startPart);
|
||||
void SortGPT(void);
|
||||
int ClearGPTData(void);
|
||||
void ChangePartType(void);
|
||||
@@ -135,6 +120,8 @@ public:
|
||||
int SaveGPTBackup(char* filename);
|
||||
int LoadGPTBackup(char* filename);
|
||||
int DestroyGPT(void); // Returns 1 if user proceeds
|
||||
|
||||
// Endianness functions
|
||||
void ReverseHeaderBytes(struct GPTHeader* header); // for endianness
|
||||
void ReversePartitionBytes(); // for endianness
|
||||
|
||||
@@ -150,8 +137,6 @@ public:
|
||||
|
||||
// Function prototypes....
|
||||
void BlankPartition(struct GPTPartition* partition);
|
||||
//int XFormType(uint8_t oldType, struct GUIDData* newType, int partNum);
|
||||
void QuickSortGPT(struct GPTPartition* partitions, int start, int finish);
|
||||
int TheyOverlap(struct GPTPartition* first, struct GPTPartition* second);
|
||||
void ChangeGPTType(struct GPTPartition* part);
|
||||
int SizesOK(void);
|
||||
|
||||
161
mbr.cc
161
mbr.cc
@@ -3,6 +3,9 @@
|
||||
|
||||
/* By Rod Smith, January to February, 2009 */
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
@@ -118,9 +121,10 @@ int MBRData::ReadMBRData(char* deviceFilename) {
|
||||
} // MBRData::ReadMBRData(char* deviceFilename)
|
||||
|
||||
// Read data from MBR.
|
||||
void MBRData::ReadMBRData(int fd) {
|
||||
int allOK = 1, i, maxLogicals = 0;
|
||||
void MBRData::ReadMBRData(int fd, int checkBlockSize) {
|
||||
int allOK = 1, i, j, maxLogicals = 0;
|
||||
int err;
|
||||
TempMBR tempMBR;
|
||||
|
||||
// Clear logical partition array
|
||||
for (i = 0; i < NUM_LOGICALS; i++) {
|
||||
@@ -136,39 +140,51 @@ void MBRData::ReadMBRData(int fd) {
|
||||
logicals[i].lengthLBA = UINT32_C(0);
|
||||
} // for
|
||||
|
||||
read(fd, code, 440);
|
||||
read(fd, &diskSignature, 4);
|
||||
read(fd, &nulls, 2);
|
||||
read(fd, partitions, 64);
|
||||
read(fd, &MBRSignature, 2);
|
||||
err = lseek64(fd, 0, SEEK_SET);
|
||||
err = read(fd, &tempMBR, 512);
|
||||
for (i = 0; i < 440; i++)
|
||||
code[i] = tempMBR.code[i];
|
||||
diskSignature = tempMBR.diskSignature;
|
||||
nulls = tempMBR.nulls;
|
||||
for (i = 0; i < 4; i++) {
|
||||
partitions[i].status = tempMBR.partitions[i].status;
|
||||
partitions[i].partitionType = tempMBR.partitions[i].partitionType;
|
||||
partitions[i].firstLBA = tempMBR.partitions[i].firstLBA;
|
||||
partitions[i].lengthLBA = tempMBR.partitions[i].lengthLBA;
|
||||
for (j = 0; j < 3; j++) {
|
||||
partitions[i].firstSector[j] = tempMBR.partitions[i].firstSector[j];
|
||||
partitions[i].lastSector[j] = tempMBR.partitions[i].lastSector[j];
|
||||
} // for j...
|
||||
} // for i...
|
||||
MBRSignature = tempMBR.MBRSignature;
|
||||
|
||||
// Reverse the byte order, if necessary
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReverseBytes((char*) &diskSignature, 4);
|
||||
ReverseBytes((char*) &nulls, 2);
|
||||
ReverseBytes((char*) &MBRSignature, 2);
|
||||
ReverseBytes(&diskSignature, 4);
|
||||
ReverseBytes(&nulls, 2);
|
||||
ReverseBytes(&MBRSignature, 2);
|
||||
for (i = 0; i < 4; i++) {
|
||||
ReverseBytes((char*) &partitions[i].firstLBA, 4);
|
||||
ReverseBytes((char*) &partitions[i].lengthLBA, 4);
|
||||
ReverseBytes(&partitions[i].firstLBA, 4);
|
||||
ReverseBytes(&partitions[i].lengthLBA, 4);
|
||||
} // for
|
||||
} // if
|
||||
|
||||
if (MBRSignature != MBR_SIGNATURE) {
|
||||
allOK = 0;
|
||||
state = invalid;
|
||||
fprintf(stderr, "MBR signature invalid; read 0x%04X, but should be 0x%04X\n",
|
||||
(unsigned int) MBRSignature, (unsigned int) MBR_SIGNATURE);
|
||||
} /* if */
|
||||
} // if
|
||||
|
||||
// Find disk size
|
||||
diskSize = disksize(fd, &err);
|
||||
|
||||
// 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
|
||||
} // if (checkBlockSize)
|
||||
|
||||
// Load logical partition data, if any is found....
|
||||
if (allOK) {
|
||||
@@ -242,33 +258,55 @@ int MBRData::WriteMBRData(void) {
|
||||
// Save the MBR data to a file. Note that this function writes ONLY the
|
||||
// MBR data, not the logical partitions (if any are defined).
|
||||
void MBRData::WriteMBRData(int fd) {
|
||||
int i;
|
||||
int i, j;
|
||||
TempMBR tempMBR;
|
||||
|
||||
// Reverse the byte order, if necessary
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReverseBytes((char*) &diskSignature, 4);
|
||||
ReverseBytes((char*) &nulls, 2);
|
||||
ReverseBytes((char*) &MBRSignature, 2);
|
||||
ReverseBytes(&diskSignature, 4);
|
||||
ReverseBytes(&nulls, 2);
|
||||
ReverseBytes(&MBRSignature, 2);
|
||||
for (i = 0; i < 4; i++) {
|
||||
ReverseBytes((char*) &partitions[i].firstLBA, 4);
|
||||
ReverseBytes((char*) &partitions[i].lengthLBA, 4);
|
||||
ReverseBytes(&partitions[i].firstLBA, 4);
|
||||
ReverseBytes(&partitions[i].lengthLBA, 4);
|
||||
} // for
|
||||
} // if
|
||||
|
||||
write(fd, code, 440);
|
||||
// Copy MBR data to a 512-byte data structure for writing, to
|
||||
// work around a FreeBSD limitation....
|
||||
for (i = 0; i < 440; i++)
|
||||
tempMBR.code[i] = code[i];
|
||||
tempMBR.diskSignature = diskSignature;
|
||||
tempMBR.nulls = nulls;
|
||||
tempMBR.MBRSignature = MBRSignature;
|
||||
for (i = 0; i < 4; i++) {
|
||||
tempMBR.partitions[i].status = partitions[i].status;
|
||||
tempMBR.partitions[i].partitionType = partitions[i].partitionType;
|
||||
tempMBR.partitions[i].firstLBA = partitions[i].firstLBA;
|
||||
tempMBR.partitions[i].lengthLBA = partitions[i].lengthLBA;
|
||||
for (j = 0; j < 3; j++) {
|
||||
tempMBR.partitions[i].firstSector[j] = partitions[i].firstSector[j];
|
||||
tempMBR.partitions[i].lastSector[j] = partitions[i].lastSector[j];
|
||||
} // for j...
|
||||
} // for i...
|
||||
|
||||
// Now write that data structure...
|
||||
write(fd, &tempMBR, 512);
|
||||
|
||||
/* write(fd, code, 440);
|
||||
write(fd, &diskSignature, 4);
|
||||
write(fd, &nulls, 2);
|
||||
write(fd, partitions, 64);
|
||||
write(fd, &MBRSignature, 2);
|
||||
write(fd, &MBRSignature, 2); */
|
||||
|
||||
// Reverse the byte order, if necessary
|
||||
// Reverse the byte order back, if necessary
|
||||
if (IsLittleEndian() == 0) {
|
||||
ReverseBytes((char*) &diskSignature, 4);
|
||||
ReverseBytes((char*) &nulls, 2);
|
||||
ReverseBytes((char*) &MBRSignature, 2);
|
||||
ReverseBytes(&diskSignature, 4);
|
||||
ReverseBytes(&nulls, 2);
|
||||
ReverseBytes(&MBRSignature, 2);
|
||||
for (i = 0; i < 4; i++) {
|
||||
ReverseBytes((char*) &partitions[i].firstLBA, 4);
|
||||
ReverseBytes((char*) &partitions[i].lengthLBA, 4);
|
||||
ReverseBytes(&partitions[i].firstLBA, 4);
|
||||
ReverseBytes(&partitions[i].lengthLBA, 4);
|
||||
} // for
|
||||
}// if
|
||||
} // MBRData::WriteMBRData(int fd)
|
||||
@@ -293,11 +331,11 @@ int MBRData::ReadLogicalPart(int fd, uint32_t extendedStart,
|
||||
(unsigned long) offset);
|
||||
partNum = -1;
|
||||
} else if (IsLittleEndian() != 1) { // Reverse byte ordering of some data....
|
||||
ReverseBytes((char*) &ebr.MBRSignature, 2);
|
||||
ReverseBytes((char*) &ebr.partitions[0].firstLBA, 4);
|
||||
ReverseBytes((char*) &ebr.partitions[0].lengthLBA, 4);
|
||||
ReverseBytes((char*) &ebr.partitions[1].firstLBA, 4);
|
||||
ReverseBytes((char*) &ebr.partitions[1].lengthLBA, 4);
|
||||
ReverseBytes(&ebr.MBRSignature, 2);
|
||||
ReverseBytes(&ebr.partitions[0].firstLBA, 4);
|
||||
ReverseBytes(&ebr.partitions[0].lengthLBA, 4);
|
||||
ReverseBytes(&ebr.partitions[1].firstLBA, 4);
|
||||
ReverseBytes(&ebr.partitions[1].lengthLBA, 4);
|
||||
} // if/else/if
|
||||
|
||||
if (ebr.MBRSignature != MBR_SIGNATURE) {
|
||||
@@ -356,14 +394,19 @@ void MBRData::DisplayMBRData(void) {
|
||||
BytesToSI(diskSize * (uint64_t) blockSize, tempStr));
|
||||
} // MBRData::DisplayMBRData()
|
||||
|
||||
// Create a protective MBR
|
||||
void MBRData::MakeProtectiveMBR(void) {
|
||||
// Create a protective MBR. Clears the boot loader area if clearBoot > 0.
|
||||
void MBRData::MakeProtectiveMBR(int clearBoot) {
|
||||
int i;
|
||||
|
||||
// Initialize variables
|
||||
nulls = 0;
|
||||
MBRSignature = MBR_SIGNATURE;
|
||||
|
||||
if (clearBoot > 0) {
|
||||
for (i = 0; i < 440; i++)
|
||||
code[i] = (uint8_t) 0;
|
||||
} // if
|
||||
|
||||
partitions[0].status = UINT8_C(0); // Flag the protective part. as unbootable
|
||||
|
||||
// Write CHS data. This maxes out the use of the disk, as much as
|
||||
@@ -467,23 +510,24 @@ struct MBRRecord* MBRData::GetPartition(int i) {
|
||||
return thePart;
|
||||
} // GetPartition()
|
||||
|
||||
// Displays the state, as a word, on stdout. Used for debugging
|
||||
// Displays the state, as a word, on stdout. Used for debugging & to
|
||||
// tell the user about the MBR state when the program launches....
|
||||
void MBRData::ShowState(void) {
|
||||
switch (state) {
|
||||
case invalid:
|
||||
printf("invalid");
|
||||
printf(" MBR: not present\n");
|
||||
break;
|
||||
case gpt:
|
||||
printf("gpt");
|
||||
printf(" MBR: protective\n");
|
||||
break;
|
||||
case hybrid:
|
||||
printf("hybrid");
|
||||
printf(" MBR: hybrid\n");
|
||||
break;
|
||||
case mbr:
|
||||
printf("mbr");
|
||||
printf(" MBR: MBR only\n");
|
||||
break;
|
||||
default:
|
||||
printf("unknown -- bug!");
|
||||
printf("\a MBR: unknown -- bug!\n");
|
||||
break;
|
||||
} // switch
|
||||
} // MBRData::ShowState()
|
||||
@@ -602,3 +646,36 @@ uint32_t MBRData::GetLength(int i) {
|
||||
retval = UINT32_C(0);
|
||||
return retval;
|
||||
} // MBRData::GetLength()
|
||||
|
||||
// Return the MBR data as a GPT partition....
|
||||
GPTPart MBRData::AsGPT(int i) {
|
||||
MBRRecord* origPart;
|
||||
GPTPart newPart;
|
||||
uint8_t origType;
|
||||
uint64_t firstSector, lastSector;
|
||||
char tempStr[NAME_SIZE];
|
||||
|
||||
newPart.BlankPartition();
|
||||
origPart = GetPartition(i);
|
||||
if (origPart != NULL) {
|
||||
origType = origPart->partitionType;
|
||||
|
||||
// don't convert extended, hybrid protective, or null (non-existent)
|
||||
// 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) &&
|
||||
(origType != 0x00) && (origType != 0xEE)) {
|
||||
firstSector = (uint64_t) origPart->firstLBA;
|
||||
newPart.SetFirstLBA(firstSector);
|
||||
lastSector = firstSector + (uint64_t) origPart->lengthLBA;
|
||||
if (lastSector > 0) lastSector--;
|
||||
newPart.SetLastLBA(lastSector);
|
||||
newPart.SetType(((uint16_t) origType) * 0x0100);
|
||||
newPart.SetUniqueGUID(1);
|
||||
newPart.SetAttributes(0);
|
||||
newPart.SetName((unsigned char*) newPart.GetNameType(tempStr));
|
||||
} // if
|
||||
} // if
|
||||
return newPart;
|
||||
} // MBRData::AsGPT()
|
||||
|
||||
21
mbr.h
21
mbr.h
@@ -1,8 +1,12 @@
|
||||
/* mbr.h -- MBR data structure definitions, types, and functions */
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "gptpart.h"
|
||||
|
||||
#ifndef __MBRSTRUCTS
|
||||
#define __MBRSTRUCTS
|
||||
@@ -32,6 +36,17 @@ struct MBRRecord {
|
||||
uint32_t lengthLBA;
|
||||
}; // struct MBRRecord
|
||||
|
||||
// Create a 512-byte data structure into which the MBR can be loaded in one
|
||||
// go, for the benefit of FreeBSD which seems to flake out when loading
|
||||
// from block devices in multiples other than the block size....
|
||||
struct TempMBR {
|
||||
uint8_t code[440];
|
||||
uint32_t diskSignature;
|
||||
uint16_t nulls;
|
||||
struct MBRRecord partitions[4];
|
||||
uint16_t MBRSignature;
|
||||
}; // struct TempMBR
|
||||
|
||||
// Extended Boot Record (EBR) data, used to hold one logical partition's
|
||||
// data within an extended partition. Includes pointer to next record for
|
||||
// in-memory linked-list access. This is similar to MBRData, but with a
|
||||
@@ -75,7 +90,7 @@ public:
|
||||
void EmptyMBR(int clearBootloader = 1);
|
||||
void SetDiskSize(uint64_t ds) {diskSize = ds;}
|
||||
int ReadMBRData(char* deviceFilename);
|
||||
void ReadMBRData(int fd);
|
||||
void ReadMBRData(int fd, int checkBlockSize = 1);
|
||||
int WriteMBRData(void);
|
||||
void WriteMBRData(int fd);
|
||||
// ReadLogicalPart() returns last partition # read to logicals[] array,
|
||||
@@ -83,8 +98,9 @@ public:
|
||||
int ReadLogicalPart(int fd, uint32_t extendedStart, uint32_t diskOffset,
|
||||
int partNum);
|
||||
void DisplayMBRData(void);
|
||||
void MakeProtectiveMBR(void);
|
||||
void MakeProtectiveMBR(int clearBoot = 0);
|
||||
MBRValidity GetValidity(void) {return state;}
|
||||
void ShowValidity(void);
|
||||
void ShowState(void);
|
||||
void MakePart(int num, uint32_t startLBA, uint32_t lengthLBA, int type = 0x07,
|
||||
int bootable = 0);
|
||||
@@ -99,6 +115,7 @@ public:
|
||||
uint8_t GetType(int i);
|
||||
uint32_t GetFirstSector(int i);
|
||||
uint32_t GetLength(int i);
|
||||
GPTPart AsGPT(int i);
|
||||
}; // struct MBRData
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// Class to manage partition type codes -- a slight variant on MBR type
|
||||
// codes, GUID type codes, and associated names.
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
22
support.cc
22
support.cc
@@ -3,6 +3,9 @@
|
||||
// Primarily by Rod Smith, February 2009, but with a few functions
|
||||
// copied from other sources (see attributions below).
|
||||
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
@@ -176,8 +179,12 @@ int GetBlockSize(int fd) {
|
||||
|
||||
#ifdef __APPLE__
|
||||
err = ioctl(fd, DKIOCGETBLOCKSIZE, &result);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
err = ioctl(fd, DIOCGSECTORSIZE, &result);
|
||||
#else
|
||||
err = ioctl(fd, BLKSSZGET, &result);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (result != 512) {
|
||||
@@ -319,15 +326,17 @@ int IsLittleEndian(void) {
|
||||
} // IsLittleEndian()
|
||||
|
||||
// Reverse the byte order of theValue; numBytes is number of bytes
|
||||
void ReverseBytes(char* theValue, int numBytes) {
|
||||
void ReverseBytes(void* theValue, int numBytes) {
|
||||
char* origValue;
|
||||
char* tempValue;
|
||||
int i;
|
||||
|
||||
origValue = (char*) theValue;
|
||||
tempValue = (char*) malloc(numBytes);
|
||||
for (i = 0; i < numBytes; i++)
|
||||
tempValue[i] = theValue[i];
|
||||
tempValue[i] = origValue[i];
|
||||
for (i = 0; i < numBytes; i++)
|
||||
theValue[i] = tempValue[numBytes - i - 1];
|
||||
origValue[i] = tempValue[numBytes - i - 1];
|
||||
free(tempValue);
|
||||
} // ReverseBytes()
|
||||
|
||||
@@ -345,6 +354,7 @@ uint64_t PowerOf2(int value) {
|
||||
return retval;
|
||||
} // PowerOf2()
|
||||
|
||||
|
||||
/**************************************************************************************
|
||||
* *
|
||||
* Below functions are lifted from various sources, as documented in comments before *
|
||||
@@ -366,6 +376,11 @@ uint64_t disksize(int fd, int *err) {
|
||||
// 32/64-bit issues on MacOS....
|
||||
#ifdef __APPLE__
|
||||
*err = ioctl(fd, DKIOCGETBLOCKCOUNT, §ors);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
*err = ioctl(fd, DIOCGMEDIASIZE, &sz);
|
||||
b = GetBlockSize(fd);
|
||||
sectors = sz / b;
|
||||
#else
|
||||
*err = ioctl(fd, BLKGETSIZE, &sz);
|
||||
if (*err) {
|
||||
@@ -378,6 +393,7 @@ uint64_t disksize(int fd, int *err) {
|
||||
sectors = sz;
|
||||
else
|
||||
sectors = (b >> 9);
|
||||
#endif
|
||||
#endif
|
||||
return sectors;
|
||||
}
|
||||
|
||||
24
support.h
24
support.h
@@ -1,8 +1,11 @@
|
||||
/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
|
||||
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined (__FreeBSD__) || defined (__APPLE__)
|
||||
// Darwin (Mac OS) only: disk IOCTLs are different, and there is no lseek64
|
||||
// This used to use __DARWIN_UNIX03 rather than __APPLE__, but __APPLE__
|
||||
// is more general. If the code fails to work on older versions of OS X/
|
||||
@@ -23,6 +26,23 @@
|
||||
// Set this as a default
|
||||
#define SECTOR_SIZE UINT32_C(512)
|
||||
|
||||
// Signatures for Apple (APM) disks, multiplied by 0x100000000
|
||||
#define APM_SIGNATURE1 UINT64_C(0x00004D5000000000)
|
||||
#define APM_SIGNATURE2 UINT64_C(0x0000535400000000)
|
||||
|
||||
/**************************
|
||||
* Some GPT constants.... *
|
||||
**************************/
|
||||
|
||||
#define GPT_SIGNATURE UINT64_C(0x5452415020494645)
|
||||
|
||||
// Number and size of GPT entries...
|
||||
#define NUM_GPT_ENTRIES 128
|
||||
#define GPT_SIZE 128
|
||||
#define HEADER_SIZE 92
|
||||
#define GPT_RESERVED 420
|
||||
#define NAME_SIZE 72
|
||||
|
||||
using namespace std;
|
||||
|
||||
// a GUID
|
||||
@@ -39,7 +59,7 @@ int GetBlockSize(int fd);
|
||||
char* GUIDToStr(struct GUIDData theGUID, char* theString);
|
||||
GUIDData GetGUID(void);
|
||||
int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian
|
||||
void ReverseBytes(char* theValue, int numBytes); // Reverses byte-order of theValue
|
||||
void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue
|
||||
uint64_t PowerOf2(int value);
|
||||
|
||||
uint64_t disksize(int fd, int* err);
|
||||
|
||||
Reference in New Issue
Block a user