Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
gptfdisk
Manage
Activity
Members
Plan
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CodeLinaro
public-release-test-restored
platform
external
gptfdisk
Commits
a0eb11a6
Commit
a0eb11a6
authored
15 years ago
by
srs5694
Browse files
Options
Downloads
Patches
Plain Diff
Added new files
parent
86dd784a
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
bsd.cc
+307
-0
307 additions, 0 deletions
bsd.cc
bsd.h
+85
-0
85 additions, 0 deletions
bsd.h
gptpart.cc
+274
-0
274 additions, 0 deletions
gptpart.cc
gptpart.h
+89
-0
89 additions, 0 deletions
gptpart.h
with
755 additions
and
0 deletions
bsd.cc
0 → 100644
+
307
−
0
View file @
a0eb11a6
/* bsd.cc -- Functions for loading, saving, and manipulating legacy BSD disklabel
data. */
/* By Rod Smith, August, 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
#include
<stdio.h>
#include
<unistd.h>
#include
<stdlib.h>
#include
<stdint.h>
#include
<fcntl.h>
#include
<string.h>
//#include <time.h>
#include
<sys/stat.h>
#include
<errno.h>
#include
"crc32.h"
#include
"support.h"
#include
"bsd.h"
using
namespace
std
;
BSDData
::
BSDData
(
void
)
{
state
=
unknown
;
signature
=
UINT32_C
(
0
);
signature2
=
UINT32_C
(
0
);
sectorSize
=
512
;
numParts
=
0
;
labelFirstLBA
=
0
;
labelLastLBA
=
0
;
labelStart
=
LABEL_OFFSET1
;
// assume raw disk format
// deviceFilename[0] = '\0';
partitions
=
NULL
;
}
// default constructor
BSDData
::~
BSDData
(
void
)
{
free
(
partitions
);
}
// destructor
int
BSDData
::
ReadBSDData
(
char
*
device
,
uint64_t
startSector
,
uint64_t
endSector
)
{
int
fd
,
allOK
=
1
;
if
((
fd
=
open
(
device
,
O_RDONLY
))
!=
-
1
)
{
ReadBSDData
(
fd
,
startSector
,
endSector
);
}
else
{
allOK
=
0
;
}
// if
close
(
fd
);
// if (allOK)
// strcpy(deviceFilename, device);
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
uint64_t
startByte
;
int
i
,
err
,
foundSig
=
0
,
bigEnd
=
0
;
int
relative
=
0
;
// assume absolute partition sector numbering
uint32_t
realSig
;
uint32_t
*
temp32
;
uint16_t
*
temp16
;
BSDRecord
*
tempRecords
;
labelFirstLBA
=
startSector
;
labelLastLBA
=
endSector
;
// 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
);
// Do some strangeness to support big-endian architectures...
bigEnd
=
(
IsLittleEndian
()
==
0
);
realSig
=
BSD_SIGNATURE
;
if
(
bigEnd
)
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
}
// if
// Load partition metadata from the buffer....
temp32
=
(
uint32_t
*
)
&
buffer
[
labelStart
+
40
];
sectorSize
=
*
temp32
;
temp16
=
(
uint16_t
*
)
&
buffer
[
labelStart
+
138
];
numParts
=
*
temp16
;
// Make it big-endian-aware....
if
(
IsLittleEndian
()
==
0
)
ReverseMetaBytes
();
// Check validity of the data and flag it appropriately....
if
(
foundSig
&&
(
numParts
<=
MAX_BSD_PARTS
))
{
state
=
bsd
;
}
else
{
state
=
bsd_invalid
;
}
// if/else
// If the state is good, go ahead and load the main partition data....
if
(
state
==
bsd
)
{
partitions
=
(
struct
BSDRecord
*
)
malloc
(
numParts
*
sizeof
(
struct
BSDRecord
));
for
(
i
=
0
;
i
<
numParts
;
i
++
)
{
// Once again, we use the buffer, but index it using a BSDRecord
// pointer (dangerous, but effective)....
tempRecords
=
(
BSDRecord
*
)
&
buffer
[
labelStart
+
148
];
partitions
[
i
].
lengthLBA
=
tempRecords
[
i
].
lengthLBA
;
partitions
[
i
].
firstLBA
=
tempRecords
[
i
].
firstLBA
;
partitions
[
i
].
fsType
=
tempRecords
[
i
].
fsType
;
if
(
bigEnd
)
{
// reverse data (fsType is a single byte)
ReverseBytes
(
&
partitions
[
i
].
lengthLBA
,
4
);
ReverseBytes
(
&
partitions
[
i
].
firstLBA
,
4
);
}
// if big-endian
// Check for signs of relative sector numbering: A "0" first sector
// number on a partition with a non-zero length -- but ONLY if the
// length is less than the disk size, since NetBSD has a habit of
// creating a disk-sized partition within a carrier MBR partition
// that's too small to house it, and this throws off everything....
if
((
partitions
[
i
].
firstLBA
==
0
)
&&
(
partitions
[
i
].
lengthLBA
>
0
)
&&
(
partitions
[
i
].
lengthLBA
<
labelLastLBA
))
relative
=
1
;
}
// for
// Some disklabels use sector numbers relative to the enclosing partition's
// start, others use absolute sector numbers. If relative numbering was
// detected above, apply a correction to all partition start sectors....
if
(
relative
)
{
for
(
i
=
0
;
i
<
numParts
;
i
++
)
{
partitions
[
i
].
firstLBA
+=
startSector
;
}
// for
}
// if
}
// if signatures OK
// DisplayBSDData();
}
// BSDData::ReadBSDData(int fd, uint64_t startSector)
// Reverse metadata's byte order; called only on big-endian systems
void
BSDData
::
ReverseMetaBytes
(
void
)
{
ReverseBytes
(
&
signature
,
4
);
ReverseBytes
(
&
sectorSize
,
4
);
ReverseBytes
(
&
signature2
,
4
);
ReverseBytes
(
&
numParts
,
2
);
}
// BSDData::ReverseMetaByteOrder()
// Display basic BSD partition data. Used for debugging.
void
BSDData
::
DisplayBSDData
(
void
)
{
int
i
;
if
(
state
==
bsd
)
{
printf
(
"BSD partitions:
\n
"
);
printf
(
"Number
\t
Start (sector)
\t
Length (sectors)
\t
Type
\n
"
);
for
(
i
=
0
;
i
<
numParts
;
i
++
)
{
printf
(
"%4d
\t
%13lu
\t
%15lu
\t
0x%02X
\n
"
,
i
+
1
,
(
unsigned
long
)
partitions
[
i
].
firstLBA
,
(
unsigned
long
)
partitions
[
i
].
lengthLBA
,
partitions
[
i
].
fsType
);
}
// for
}
// if
}
// BSDData::DisplayBSDData()
// Displays the BSD disklabel state. Called during program launch to inform
// the user about the partition table(s) status
int
BSDData
::
ShowState
(
void
)
{
int
retval
=
0
;
switch
(
state
)
{
case
bsd_invalid
:
printf
(
" BSD: not present
\n
"
);
break
;
case
bsd
:
printf
(
" BSD: present
\n
"
);
retval
=
1
;
break
;
default:
printf
(
"
\a
BSD: unknown -- bug!
\n
"
);
break
;
}
// switch
return
retval
;
}
// BSDData::ShowState()
// Returns the BSD table's partition type code
uint8_t
BSDData
::
GetType
(
int
i
)
{
uint8_t
retval
=
0
;
// 0 = "unused"
if
((
i
<
numParts
)
&&
(
i
>=
0
)
&&
(
state
==
bsd
)
&&
(
partitions
!=
0
))
retval
=
partitions
[
i
].
fsType
;
return
(
retval
);
}
// BSDData::GetType()
// Returns the number of the first sector of the specified partition
uint64_t
BSDData
::
GetFirstSector
(
int
i
)
{
uint64_t
retval
=
UINT64_C
(
0
);
if
((
i
<
numParts
)
&&
(
i
>=
0
)
&&
(
state
==
bsd
)
&&
(
partitions
!=
0
))
retval
=
(
uint64_t
)
partitions
[
i
].
firstLBA
;
return
retval
;
}
// BSDData::GetFirstSector
// Returns the length (in sectors) of the specified partition
uint64_t
BSDData
::
GetLength
(
int
i
)
{
uint64_t
retval
=
UINT64_C
(
0
);
if
((
i
<
numParts
)
&&
(
i
>=
0
)
&&
(
state
==
bsd
)
&&
(
partitions
!=
0
))
retval
=
(
uint64_t
)
partitions
[
i
].
lengthLBA
;
return
retval
;
}
// BSDData::GetLength()
// Returns the number of partitions defined in the current table
int
BSDData
::
GetNumParts
(
void
)
{
return
numParts
;
}
// BSDData::GetNumParts()
// Returns the specified partition as a GPT partition. Used in BSD-to-GPT
// conversion process
GPTPart
BSDData
::
AsGPT
(
int
i
)
{
GPTPart
guid
;
// dump data in here, then return it
uint64_t
sectorOne
,
sectorEnd
;
// first & last sectors of partition
char
tempStr
[
NAME_SIZE
];
// temporary string for holding GPT name
int
passItOn
=
1
;
// Set to 0 if partition is empty or invalid
guid
.
BlankPartition
();
sectorOne
=
(
uint64_t
)
partitions
[
i
].
firstLBA
;
sectorEnd
=
sectorOne
+
(
uint64_t
)
partitions
[
i
].
lengthLBA
;
if
(
sectorEnd
>
0
)
sectorEnd
--
;
// Note on above: BSD partitions sometimes have a length of 0 and a start
// sector of 0. With unsigned ints, the usual (start + length - 1) to
// find the end will result in a huge number, which will be confusing
// Do a few sanity checks on the partition before we pass it on....
// First, check that it falls within the bounds of its container
// and that it starts before it ends....
if
((
sectorOne
<
labelFirstLBA
)
||
(
sectorEnd
>
labelLastLBA
)
||
(
sectorOne
>
sectorEnd
))
passItOn
=
0
;
// Some disklabels include a pseudo-partition that's the size of the entire
// disk or containing partition. Don't return it.
if
((
sectorOne
<=
labelFirstLBA
)
&&
(
sectorEnd
>=
labelLastLBA
)
&&
(
GetType
(
i
)
==
0
))
passItOn
=
0
;
// If the end point is 0, it's not a valid partition.
if
(
sectorEnd
==
0
)
passItOn
=
0
;
if
(
passItOn
)
{
guid
.
SetFirstLBA
(
sectorOne
);
guid
.
SetLastLBA
(
sectorEnd
);
// Now set a random unique GUID for the partition....
guid
.
SetUniqueGUID
(
1
);
// ... zero out the attributes and name fields....
guid
.
SetAttributes
(
UINT64_C
(
0
));
// Most BSD disklabel type codes seem to be archaic or rare.
// They're also ambiguous; a FreeBSD filesystem is impossible
// to distinguish from a NetBSD one. Thus, these code assignment
// are going to be rough to begin with. For a list of meanings,
// see http://fxr.watson.org/fxr/source/sys/dtype.h?v=DFBSD,
// or Google it.
switch
(
GetType
(
i
))
{
case
1
:
// BSD swap
guid
.
SetType
(
0xa502
);
break
;
case
7
:
// BSD FFS
guid
.
SetType
(
0xa503
);
break
;
case
8
:
case
11
:
// MS-DOS or HPFS
guid
.
SetType
(
0x0700
);
break
;
case
9
:
// log-structured fs
guid
.
SetType
(
0xa903
);
break
;
case
13
:
// bootstrap
guid
.
SetType
(
0xa501
);
break
;
case
14
:
// vinum
guid
.
SetType
(
0xa505
);
break
;
case
15
:
// RAID
guid
.
SetType
(
0xa903
);
break
;
case
27
:
// FreeBSD ZFS
guid
.
SetType
(
0xa504
);
break
;
default:
guid
.
SetType
(
0x0700
);
break
;
}
// switch
// Set the partition name to the name of the type code....
guid
.
SetName
((
unsigned
char
*
)
guid
.
GetNameType
(
tempStr
));
}
// if
return
guid
;
}
// BSDData::AsGPT()
This diff is collapsed.
Click to expand it.
bsd.h
0 → 100644
+
85
−
0
View file @
a0eb11a6
/* bsd.h -- BSD disklabel 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 __BSD_STRUCTS
#define __BSD_STRUCTS
#define BSD_SIGNATURE UINT32_C(0x82564557)
#define LABEL_OFFSET1 64
/* BSD disklabels can start at one of these two */
#define LABEL_OFFSET2 512
/* values; check both for valid signatures */
// FreeBSD documents a maximum # of partitions of 8, but I saw 16 on a NetBSD
// disk. I'm quadrupling that for further safety. Note that BSDReadData()
// uses a 2048-byte I/O buffer. In combination with LABEL_OFFSET2 and the
// additional 148-byte offset to the actual partition data, that gives a
// theoretical maximum of 86.75 partitions that the program can handle.
#define MAX_BSD_PARTS 64
using
namespace
std
;
/****************************************
* *
* BSDData class and related structures *
* *
****************************************/
// Possible states of the MBR
enum
BSDValidity
{
unknown
,
bsd_invalid
,
bsd
};
// Data for a single BSD partition record
struct
BSDRecord
{
// the partition table
uint32_t
lengthLBA
;
// number of sectors in partition
uint32_t
firstLBA
;
// starting sector
uint32_t
fragSize
;
// filesystem basic fragment size
uint8_t
fsType
;
// filesystem type, see below
uint8_t
frag
;
// filesystem fragments per block
uint16_t
pcpg
;
/* filesystem cylinders per group */
// was u_uint16_t
};
// Full data in tweaked MBR format
class
BSDData
{
protected:
// We only need a few items from the main BSD disklabel data structure....
uint32_t
signature
;
// the magic number
uint32_t
sectorSize
;
// # of bytes per sector
uint32_t
signature2
;
// the magic number (again)
uint16_t
numParts
;
// number of partitions in table
BSDRecord
*
partitions
;
// partition array
// Above are basic BSD disklabel data; now add more stuff....
// uint64_t offset; // starting point in blocks
uint64_t
labelStart
;
// BSD disklabel start point in bytes from firstLBA
uint64_t
labelFirstLBA
;
// first sector of BSD disklabel (partition or disk)
uint64_t
labelLastLBA
;
// final sector of BSD disklabel
// char deviceFilename[256];
BSDValidity
state
;
// struct BSDRecord* GetPartition(int i); // Return BSD partition
public:
BSDData
(
void
);
~
BSDData
(
void
);
int
ReadBSDData
(
char
*
deviceFilename
,
uint64_t
startSector
,
uint64_t
endSector
);
void
ReadBSDData
(
int
fd
,
uint64_t
startSector
,
uint64_t
endSector
);
void
ReverseMetaBytes
(
void
);
void
DisplayBSDData
(
void
);
// int ConvertBSDParts(struct GPTPartition gptParts[]);
int
ShowState
(
void
);
// returns 1 if BSD disklabel detected
int
IsDisklabel
(
void
)
{
return
(
state
==
bsd
);}
// Functions to extract data on specific partitions....
uint8_t
GetType
(
int
i
);
uint64_t
GetFirstSector
(
int
i
);
uint64_t
GetLength
(
int
i
);
int
GetNumParts
(
void
);
GPTPart
AsGPT
(
int
i
);
// Return BSD part. as GPT part.
};
// struct MBRData
#endif
This diff is collapsed.
Click to expand it.
gptpart.cc
0 → 100644
+
274
−
0
View file @
a0eb11a6
//
// C++ Implementation: gptpart
//
// Description: Class to implement a SINGLE GPT partition
//
//
// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
/* 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
#include
<stdio.h>
#include
<string.h>
#include
"gptpart.h"
#include
"attributes.h"
using
namespace
std
;
PartTypes
GPTPart
::
typeHelper
;
GPTPart
::
GPTPart
(
void
)
{
}
// Default constructor
GPTPart
::~
GPTPart
(
void
)
{
}
// destructor
// Return partition's name field
unsigned
char
*
GPTPart
::
GetName
(
unsigned
char
*
ref
)
{
if
(
ref
==
NULL
)
ref
=
(
unsigned
char
*
)
malloc
(
NAME_SIZE
*
sizeof
(
unsigned
char
));
strcpy
((
char
*
)
ref
,
(
char
*
)
name
);
return
ref
;
}
// GPTPart::GetName()
// Return the gdisk-specific two-byte hex code for the partition
uint16_t
GPTPart
::
GetHexType
(
void
)
{
return
typeHelper
.
GUIDToID
(
partitionType
);
}
// GPTPart::GetHexType()
// Return a plain-text description of the partition type (e.g., "Linux/Windows
// data" or "Linux swap").
char
*
GPTPart
::
GetNameType
(
char
*
theName
)
{
return
typeHelper
.
GUIDToName
(
partitionType
,
theName
);
}
// GPTPart::GetNameType()
// Compute and return the partition's length (or 0 if the end is incorrectly
// set before the beginning).
uint64_t
GPTPart
::
GetLengthLBA
(
void
)
{
uint64_t
length
=
0
;
if
(
firstLBA
<=
lastLBA
)
length
=
lastLBA
-
firstLBA
+
UINT64_C
(
1
);
return
length
;
}
// GPTPart::GetLengthLBA()
GPTPart
&
GPTPart
::
operator
=
(
const
GPTPart
&
orig
)
{
int
i
;
partitionType
=
orig
.
partitionType
;
uniqueGUID
=
orig
.
uniqueGUID
;
firstLBA
=
orig
.
firstLBA
;
lastLBA
=
orig
.
lastLBA
;
attributes
=
orig
.
attributes
;
for
(
i
=
0
;
i
<
NAME_SIZE
;
i
++
)
name
[
i
]
=
orig
.
name
[
i
];
}
// assignment operator
// Sets the unique GUID to a value of 0 or a random value,
// depending on the parameter: 0 = 0, anything else = random
void
GPTPart
::
SetUniqueGUID
(
int
zeroOrRandom
)
{
if
(
zeroOrRandom
==
0
)
{
uniqueGUID
.
data1
=
0
;
uniqueGUID
.
data2
=
0
;
}
else
{
// rand() is only 32 bits on 32-bit systems, so multiply together to
// fill a 64-bit value.
uniqueGUID
.
data1
=
(
uint64_t
)
rand
()
*
(
uint64_t
)
rand
();
uniqueGUID
.
data2
=
(
uint64_t
)
rand
()
*
(
uint64_t
)
rand
();
}
}
// GPTPart::SetUniqueGUID()
// Blank (delete) a single partition
void
GPTPart
::
BlankPartition
(
void
)
{
int
j
;
GUIDData
zeroGUID
;
zeroGUID
.
data1
=
0
;
zeroGUID
.
data2
=
0
;
uniqueGUID
=
zeroGUID
;
partitionType
=
zeroGUID
;
firstLBA
=
0
;
lastLBA
=
0
;
attributes
=
0
;
for
(
j
=
0
;
j
<
NAME_SIZE
;
j
++
)
name
[
j
]
=
'\0'
;
}
// GPTPart::BlankPartition
// Returns 1 if the two partitions overlap, 0 if they don't
int
GPTPart
::
DoTheyOverlap
(
GPTPart
*
other
)
{
int
theyDo
=
0
;
// Don't bother checking unless these are defined (both start and end points
// are 0 for undefined partitions, so just check the start points)
if
((
firstLBA
!=
0
)
&&
(
other
->
firstLBA
!=
0
))
{
if
((
firstLBA
<
other
->
lastLBA
)
&&
(
lastLBA
>=
other
->
firstLBA
))
theyDo
=
1
;
if
((
other
->
firstLBA
<
lastLBA
)
&&
(
other
->
lastLBA
>=
firstLBA
))
theyDo
=
1
;
}
// if
return
(
theyDo
);
}
// GPTPart::DoTheyOverlap()
// Reverse the bytes of integral data types; used on big-endian systems.
void
GPTPart
::
ReversePartBytes
(
void
)
{
ReverseBytes
(
&
partitionType
.
data1
,
8
);
ReverseBytes
(
&
partitionType
.
data2
,
8
);
ReverseBytes
(
&
uniqueGUID
.
data1
,
8
);
ReverseBytes
(
&
uniqueGUID
.
data2
,
8
);
ReverseBytes
(
&
firstLBA
,
8
);
ReverseBytes
(
&
lastLBA
,
8
);
ReverseBytes
(
&
attributes
,
8
);
}
// GPTPart::ReverseBytes()
// Display summary information; does nothing if the partition is empty.
void
GPTPart
::
ShowSummary
(
int
i
,
uint32_t
blockSize
,
char
*
sizeInSI
)
{
int
j
;
if
(
firstLBA
!=
0
)
{
BytesToSI
(
blockSize
*
(
lastLBA
-
firstLBA
+
1
),
sizeInSI
);
printf
(
"%4d %14lu %14lu"
,
i
+
1
,
(
unsigned
long
)
firstLBA
,
(
unsigned
long
)
lastLBA
);
printf
(
" %-10s %04X "
,
sizeInSI
,
typeHelper
.
GUIDToID
(
partitionType
));
j
=
0
;
while
((
name
[
j
]
!=
'\0'
)
&&
(
j
<
44
))
{
printf
(
"%c"
,
name
[
j
]);
j
+=
2
;
}
// while
printf
(
"
\n
"
);
}
// if
}
// GPTPart::ShowSummary()
// Show detailed partition information. Does nothing if the partition is
// empty (as determined by firstLBA being 0).
void
GPTPart
::
ShowDetails
(
uint32_t
blockSize
)
{
char
temp
[
255
];
int
i
;
uint64_t
size
;
if
(
firstLBA
!=
0
)
{
printf
(
"Partition GUID code: %s "
,
GUIDToStr
(
partitionType
,
temp
));
printf
(
"(%s)
\n
"
,
typeHelper
.
GUIDToName
(
partitionType
,
temp
));
printf
(
"Partition unique GUID: %s
\n
"
,
GUIDToStr
(
uniqueGUID
,
temp
));
printf
(
"First sector: %llu (at %s)
\n
"
,
(
unsigned
long
long
)
firstLBA
,
BytesToSI
(
firstLBA
*
blockSize
,
temp
));
printf
(
"Last sector: %llu (at %s)
\n
"
,
(
unsigned
long
long
)
lastLBA
,
BytesToSI
(
lastLBA
*
blockSize
,
temp
));
size
=
(
lastLBA
-
firstLBA
+
1
);
printf
(
"Partition size: %llu sectors (%s)
\n
"
,
(
unsigned
long
long
)
size
,
BytesToSI
(
size
*
((
uint64_t
)
blockSize
),
temp
));
printf
(
"Attribute flags: %016llx
\n
"
,
(
unsigned
long
long
)
attributes
);
printf
(
"Partition name: "
);
i
=
0
;
while
((
name
[
i
]
!=
'\0'
)
&&
(
i
<
NAME_SIZE
))
{
printf
(
"%c"
,
name
[
i
]);
i
+=
2
;
}
// while
printf
(
"
\n
"
);
}
// if
}
// GPTPart::ShowDetails()
/****************************************
* Functions requiring user interaction *
****************************************/
// Change the type code on the partition.
void
GPTPart
::
ChangeType
(
void
)
{
char
typeName
[
255
],
line
[
255
];
int
typeNum
=
0xFFFF
;
// uint16_t typeNum = 0xFFFF;
GUIDData
newType
;
printf
(
"Current type is '%s'
\n
"
,
GetNameType
(
line
));
// printf("Current type is '%s'\n", typeHelper.GUIDToName(partitionType, typeName));
while
((
!
typeHelper
.
Valid
(
typeNum
))
&&
(
typeNum
!=
0
))
{
printf
(
"Hex code (L to show codes, 0 to enter raw code): "
);
fgets
(
line
,
255
,
stdin
);
sscanf
(
line
,
"%X"
,
&
typeNum
);
if
((
line
[
0
]
==
'L'
)
||
(
line
[
0
]
==
'l'
))
typeHelper
.
ShowTypes
();
}
// while
if
(
typeNum
!=
0
)
// user entered a code, so convert it
newType
=
typeHelper
.
IDToGUID
((
uint16_t
)
typeNum
);
else
// user wants to enter the GUID directly, so do that
newType
=
GetGUID
();
partitionType
=
newType
;
printf
(
"Changed system type of partition to '%s'
\n
"
,
typeHelper
.
GUIDToName
(
partitionType
,
typeName
));
}
// GPTPart::ChangeType()
// Set the name for a partition to theName, or prompt for a name if
// theName is a NULL pointer. Note that theName is a standard C-style
// string, although the GUID partition definition requires a UTF-16LE
// string. This function creates a simple-minded copy for this.
void
GPTPart
::
SetName
(
unsigned
char
*
theName
)
{
char
newName
[
NAME_SIZE
];
// New name
int
i
;
// Blank out new name string, just to be on the safe side....
for
(
i
=
0
;
i
<
NAME_SIZE
;
i
++
)
newName
[
i
]
=
'\0'
;
if
(
theName
==
NULL
)
{
// No name specified, so get one from the user
printf
(
"Enter name: "
);
fgets
(
newName
,
NAME_SIZE
/
2
,
stdin
);
// Input is likely to include a newline, so remove it....
i
=
strlen
(
newName
);
if
(
newName
[
i
-
1
]
==
'\n'
)
newName
[
i
-
1
]
=
'\0'
;
}
else
{
strcpy
(
newName
,
(
char
*
)
theName
);
}
// if
// Copy the C-style ASCII string from newName into a form that the GPT
// table will accept....
for
(
i
=
0
;
i
<
NAME_SIZE
;
i
++
)
{
if
((
i
%
2
)
==
0
)
{
name
[
i
]
=
newName
[(
i
/
2
)];
}
else
{
name
[
i
]
=
'\0'
;
}
// if/else
}
// for
}
// GPTPart::SetName()
/***********************************
* Non-class but related functions *
***********************************/
// Recursive quick sort algorithm for GPT partitions. Note that if there
// are any empties in the specified range, they'll be sorted to the
// start, resulting in a sorted set of partitions that begins with
// partition 2, 3, or higher.
void
QuickSortGPT
(
GPTPart
*
partitions
,
int
start
,
int
finish
)
{
uint64_t
starterValue
;
// starting location of median partition
int
left
,
right
;
GPTPart
temp
;
left
=
start
;
right
=
finish
;
starterValue
=
partitions
[(
start
+
finish
)
/
2
].
GetFirstLBA
();
do
{
while
(
partitions
[
left
].
GetFirstLBA
()
<
starterValue
)
left
++
;
while
(
partitions
[
right
].
GetFirstLBA
()
>
starterValue
)
right
--
;
if
(
left
<=
right
)
{
temp
=
partitions
[
left
];
partitions
[
left
]
=
partitions
[
right
];
partitions
[
right
]
=
temp
;
left
++
;
right
--
;
}
// if
}
while
(
left
<=
right
);
if
(
start
<
right
)
QuickSortGPT
(
partitions
,
start
,
right
);
if
(
finish
>
left
)
QuickSortGPT
(
partitions
,
left
,
finish
);
}
// QuickSortGPT()
This diff is collapsed.
Click to expand it.
gptpart.h
0 → 100644
+
89
−
0
View file @
a0eb11a6
//
// C++ Interface: gptpart
//
// Description: Class to implement a single GPT partition
//
//
// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
/* 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. */
#ifndef __GPTPART_H
#define __GPTPART_H
#include
<stdint.h>
#include
<sys/types.h>
#include
<sys/ioctl.h>
#include
"support.h"
#include
"parttypes.h"
using
namespace
std
;
/*****************************************
* *
* GUIDPart class and related structures *
* *
*****************************************/
class
GPTPart
{
protected:
// Caution: The non-static data in GUIDPart is precisely the right size
// to enable easy loading of the data directly from disk. If any
// non-static variables are added to the below, the data size will
// change and the program will stop working. This can be corrected by
// adjusting the data-load operation in GPTData::LoadMainTable() and
// GPTData::LoadSecondTableAsMain() and then removing the GUIDPart
// size check in SizesOK().
struct
GUIDData
partitionType
;
struct
GUIDData
uniqueGUID
;
uint64_t
firstLBA
;
uint64_t
lastLBA
;
uint64_t
attributes
;
unsigned
char
name
[
NAME_SIZE
];
static
PartTypes
typeHelper
;
public:
GPTPart
(
void
);
~
GPTPart
(
void
);
// Simple data retrieval:
struct
GUIDData
GetType
(
void
)
{
return
partitionType
;}
uint16_t
GetHexType
(
void
);
char
*
GetNameType
(
char
*
theName
);
struct
GUIDData
GetUniqueGUID
(
void
)
{
return
uniqueGUID
;}
uint64_t
GetFirstLBA
(
void
)
{
return
firstLBA
;}
uint64_t
GetLastLBA
(
void
)
{
return
lastLBA
;}
uint64_t
GetLengthLBA
(
void
);
uint64_t
GetAttributes
(
void
)
{
return
attributes
;}
unsigned
char
*
GetName
(
unsigned
char
*
theName
);
// Simple data assignment:
void
SetType
(
struct
GUIDData
t
)
{
partitionType
=
t
;}
void
SetType
(
uint16_t
hex
)
{
partitionType
=
typeHelper
.
IDToGUID
(
hex
);}
void
SetUniqueGUID
(
struct
GUIDData
u
)
{
uniqueGUID
=
u
;}
void
SetUniqueGUID
(
int
zeroOrRandom
);
void
SetFirstLBA
(
uint64_t
f
)
{
firstLBA
=
f
;}
void
SetLastLBA
(
uint64_t
l
)
{
lastLBA
=
l
;}
void
SetAttributes
(
uint64_t
a
)
{
attributes
=
a
;}
void
SetName
(
unsigned
char
*
n
);
// Additional functions
GPTPart
&
operator
=
(
const
GPTPart
&
orig
);
void
ShowSummary
(
int
i
,
uint32_t
blockSize
,
char
*
sizeInSI
);
// display summary information (1-line)
void
ShowDetails
(
uint32_t
blockSize
);
// display detailed information (multi-line)
void
BlankPartition
(
void
);
// empty partition of data
int
DoTheyOverlap
(
GPTPart
*
other
);
// returns 1 if there's overlap
void
ReversePartBytes
(
void
);
// reverse byte order of all integer fields
// Functions requiring user interaction
void
ChangeType
(
void
);
// Change the type code
};
// struct GPTPart
// A support function that doesn't quite belong in the class....
void
QuickSortGPT
(
GPTPart
*
partitions
,
int
start
,
int
finish
);
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment