blob: b5bf7710999d25a152ec932f37e8a68c4a6284a5 [file] [log] [blame]
srs5694a0eb11a2009-08-29 15:00:08 -04001//
2// C++ Implementation: gptpart
3//
4// Description: Class to implement a SINGLE GPT partition
5//
6//
7// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
srs5694978041c2009-09-21 20:51:47 -040012// This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
13// under the terms of the GNU GPL version 2, as detailed in the COPYING file.
srs5694a0eb11a2009-08-29 15:00:08 -040014
15#define __STDC_LIMIT_MACROS
16#define __STDC_CONSTANT_MACROS
17
srs5694a0eb11a2009-08-29 15:00:08 -040018#include <string.h>
srs5694fed16d02010-01-27 23:03:40 -050019#include <stdio.h>
srs56945a608532011-03-17 13:53:01 -040020#include <unicode/ustdio.h>
srs5694fed16d02010-01-27 23:03:40 -050021#include <iostream>
srs5694a0eb11a2009-08-29 15:00:08 -040022#include "gptpart.h"
23#include "attributes.h"
24
25using namespace std;
26
srs5694a0eb11a2009-08-29 15:00:08 -040027GPTPart::GPTPart(void) {
srs569455d92612010-03-07 22:16:07 -050028 partitionType.Zero();
29 uniqueGUID.Zero();
30 firstLBA = 0;
31 lastLBA = 0;
32 attributes = 0;
srs569464cbd172011-03-01 22:03:54 -050033 memset(name, 0, NAME_SIZE);
srs5694a0eb11a2009-08-29 15:00:08 -040034} // Default constructor
35
36GPTPart::~GPTPart(void) {
37} // destructor
38
srs5694a0eb11a2009-08-29 15:00:08 -040039// Return the gdisk-specific two-byte hex code for the partition
srs5694bf8950c2011-03-12 01:23:12 -050040uint16_t GPTPart::GetHexType(void) const {
srs56946699b012010-02-04 00:55:30 -050041 return partitionType.GetHexType();
srs5694a0eb11a2009-08-29 15:00:08 -040042} // GPTPart::GetHexType()
43
44// Return a plain-text description of the partition type (e.g., "Linux/Windows
45// data" or "Linux swap").
srs56946699b012010-02-04 00:55:30 -050046string GPTPart::GetTypeName(void) {
47 return partitionType.TypeName();
srs5694a0eb11a2009-08-29 15:00:08 -040048} // GPTPart::GetNameType()
49
srs56945a608532011-03-17 13:53:01 -040050// Return a Unicode description of the partition type (e.g., "Linux/Windows
51// data" or "Linux swap").
52UnicodeString GPTPart::GetUTypeName(void) {
53 return partitionType.UTypeName();
54/* UnicodeString temp;
55
56 temp = temp.fromUTF8(partitionType.TypeName());
57 return temp; */
58} // GPTPart::GetNameType()
59
srs5694a0eb11a2009-08-29 15:00:08 -040060// Compute and return the partition's length (or 0 if the end is incorrectly
61// set before the beginning).
srs5694bf8950c2011-03-12 01:23:12 -050062uint64_t GPTPart::GetLengthLBA(void) const {
srs5694a0eb11a2009-08-29 15:00:08 -040063 uint64_t length = 0;
srs569455d92612010-03-07 22:16:07 -050064
srs5694a0eb11a2009-08-29 15:00:08 -040065 if (firstLBA <= lastLBA)
66 length = lastLBA - firstLBA + UINT64_C(1);
67 return length;
68} // GPTPart::GetLengthLBA()
69
srs56945a608532011-03-17 13:53:01 -040070/* // Return partition's name field, converted to a C++ ASCII string
srs56946699b012010-02-04 00:55:30 -050071string GPTPart::GetDescription(void) {
srs56940a697312010-01-28 21:10:52 -050072 string theName;
srs5694a0eb11a2009-08-29 15:00:08 -040073 int i;
74
srs56940a697312010-01-28 21:10:52 -050075 theName = "";
76 for (i = 0; i < NAME_SIZE; i += 2) {
77 if (name[i] != '\0')
78 theName += name[i];
79 } // for
80 return theName;
srs56945a608532011-03-17 13:53:01 -040081} // GPTPart::GetDescription() */
82
83UnicodeString GPTPart::GetDescription(void) {
84 UnicodeString theName;
85 UChar *temp;
86 int i;
87
88 theName = "";
89 temp = (UChar*) name;
90 for (i = 0; i < NAME_SIZE / 2; i++) {
91 if (temp[i] != '\0')
92 theName += temp[i];
93 } // for
94 return theName;
srs56946699b012010-02-04 00:55:30 -050095} // GPTPart::GetDescription()
srs56940a697312010-01-28 21:10:52 -050096
srs569408bb0da2010-02-19 17:19:55 -050097// Return 1 if the partition is in use
98int GPTPart::IsUsed(void) {
99 return (firstLBA != UINT64_C(0));
100} // GPTPart::IsUsed()
101
srs56940a697312010-01-28 21:10:52 -0500102// Set the type code to the specified one. Also changes the partition
103// name *IF* the current name is the generic one for the current partition
104// type.
srs56946699b012010-02-04 00:55:30 -0500105void GPTPart::SetType(PartType t) {
srs56945a608532011-03-17 13:53:01 -0400106 if (GetDescription() == partitionType.UTypeName()) {
srs56946699b012010-02-04 00:55:30 -0500107 SetName(t.TypeName());
srs56940a697312010-01-28 21:10:52 -0500108 } // if
109 partitionType = t;
110} // GPTPart::SetType()
srs5694a0eb11a2009-08-29 15:00:08 -0400111
srs5694a0eb11a2009-08-29 15:00:08 -0400112// Set the name for a partition to theName, or prompt for a name if
srs56945a608532011-03-17 13:53:01 -0400113// theName is empty, using a C++-style string as input.
114void GPTPart::SetName(string theName) {
115 UnicodeString uString;
srs5694a0eb11a2009-08-29 15:00:08 -0400116
srs56945a608532011-03-17 13:53:01 -0400117 uString = theName.c_str();
118 SetName(uString);
119} // GPTPart::SetName()
120
121// Set the name for a partition to theName, or prompt for a name
122// if theName is empty, using a Unicode string as input.
123void GPTPart::SetName(UnicodeString theName) {
124 int i;
125 UChar temp[NAME_SIZE / 2];
srs5694a0eb11a2009-08-29 15:00:08 -0400126
srs5694fed16d02010-01-27 23:03:40 -0500127 if (theName == "") { // No name specified, so get one from the user
128 cout << "Enter name: ";
srs56945a608532011-03-17 13:53:01 -0400129 theName = ReadUString();
srs5694a0eb11a2009-08-29 15:00:08 -0400130 } // if
131
srs56945a608532011-03-17 13:53:01 -0400132 // Copy the C++-style string from newName into a form that the GPT
srs5694a0eb11a2009-08-29 15:00:08 -0400133 // table will accept....
srs56945a608532011-03-17 13:53:01 -0400134 memset(temp, 0, NAME_SIZE);
135 for (i = 0; i < theName.length(); i++)
136 temp[i] = theName[i];
137 memcpy(name, temp, NAME_SIZE);
srs5694a0eb11a2009-08-29 15:00:08 -0400138} // GPTPart::SetName()
139
srs56946699b012010-02-04 00:55:30 -0500140// Set the name for the partition based on the current GUID partition type
141// code's associated name
142void GPTPart::SetDefaultDescription(void) {
143 SetName(partitionType.TypeName());
144} // GPTPart::SetDefaultDescription()
145
srs56940a697312010-01-28 21:10:52 -0500146GPTPart & GPTPart::operator=(const GPTPart & orig) {
srs56940a697312010-01-28 21:10:52 -0500147 partitionType = orig.partitionType;
148 uniqueGUID = orig.uniqueGUID;
149 firstLBA = orig.firstLBA;
150 lastLBA = orig.lastLBA;
151 attributes = orig.attributes;
srs569464cbd172011-03-01 22:03:54 -0500152 memcpy(name, orig.name, NAME_SIZE);
srs56940a697312010-01-28 21:10:52 -0500153 return *this;
154} // assignment operator
155
srs56949a46b042011-03-15 00:34:10 -0400156// Compare the values, and return a bool result.
157// Because this is intended for sorting and a firstLBA value of 0 denotes
158// a partition that's not in use and so that should be sorted upwards,
159// we return the opposite of the usual arithmetic result when either
160// firstLBA value is 0.
161bool GPTPart::operator<(const GPTPart &other) const {
srs56949a46b042011-03-15 00:34:10 -0400162 if (firstLBA && other.firstLBA)
163 return (firstLBA < other.firstLBA);
164 else
165 return (other.firstLBA < firstLBA);
166} // GPTPart::operator<()
167
srs56940a697312010-01-28 21:10:52 -0500168// Display summary information; does nothing if the partition is empty.
169void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
srs569401f7f082011-03-15 23:53:31 -0400170 string sizeInIeee;
srs56945a608532011-03-17 13:53:01 -0400171 UnicodeString description;
srs569464cbd172011-03-01 22:03:54 -0500172 size_t i;
srs56940a697312010-01-28 21:10:52 -0500173
174 if (firstLBA != 0) {
srs569401f7f082011-03-15 23:53:31 -0400175 sizeInIeee = BytesToIeee(lastLBA - firstLBA + 1, blockSize);
srs569408bb0da2010-02-19 17:19:55 -0500176 cout.fill(' ');
srs56940a697312010-01-28 21:10:52 -0500177 cout.width(4);
178 cout << partNum + 1 << " ";
179 cout.width(14);
180 cout << firstLBA << " ";
181 cout.width(14);
182 cout << lastLBA << " ";
srs569401f7f082011-03-15 23:53:31 -0400183 cout << BytesToIeee(lastLBA - firstLBA + 1, blockSize) << " ";
184 if (sizeInIeee.length() < 10)
185 for (i = 0; i < 10 - sizeInIeee.length(); i++)
186 cout << " ";
srs56940a697312010-01-28 21:10:52 -0500187 cout.fill('0');
188 cout.width(4);
189 cout.setf(ios::uppercase);
srs56946699b012010-02-04 00:55:30 -0500190 cout << hex << partitionType.GetHexType() << " " << dec;
srs56940a697312010-01-28 21:10:52 -0500191 cout.fill(' ');
srs56945a608532011-03-17 13:53:01 -0400192// description = GetDescription();
193 GetDescription().extractBetween(0, 24, description);
194 cout << description << "\n";
195// for (i = 0; i < 23; i++)
196// cout << (char) description.;
197// cout << GetDescription().tempSubString(0, 23) << "\n";
198// cout << GetDescription().substr(0, 23) << "\n";
srs56940a697312010-01-28 21:10:52 -0500199 cout.fill(' ');
200 } // if
201} // GPTPart::ShowSummary()
202
203// Show detailed partition information. Does nothing if the partition is
204// empty (as determined by firstLBA being 0).
205void GPTPart::ShowDetails(uint32_t blockSize) {
206 uint64_t size;
207
208 if (firstLBA != 0) {
srs56945a081752010-09-24 20:39:41 -0400209 cout << "Partition GUID code: " << partitionType;
srs56946699b012010-02-04 00:55:30 -0500210 cout << " (" << partitionType.TypeName() << ")\n";
srs56945a081752010-09-24 20:39:41 -0400211 cout << "Partition unique GUID: " << uniqueGUID << "\n";
srs56940a697312010-01-28 21:10:52 -0500212
213 cout << "First sector: " << firstLBA << " (at "
srs569401f7f082011-03-15 23:53:31 -0400214 << BytesToIeee(firstLBA, blockSize) << ")\n";
srs56940a697312010-01-28 21:10:52 -0500215 cout << "Last sector: " << lastLBA << " (at "
srs569401f7f082011-03-15 23:53:31 -0400216 << BytesToIeee(lastLBA, blockSize) << ")\n";
srs56940a697312010-01-28 21:10:52 -0500217 size = (lastLBA - firstLBA + 1);
218 cout << "Partition size: " << size << " sectors ("
srs569401f7f082011-03-15 23:53:31 -0400219 << BytesToIeee(size, blockSize) << ")\n";
srs56940a697312010-01-28 21:10:52 -0500220 cout << "Attribute flags: ";
221 cout.fill('0');
222 cout.width(16);
223 cout << hex;
224 cout << attributes << "\n";
225 cout << dec;
srs56946699b012010-02-04 00:55:30 -0500226 cout << "Partition name: " << GetDescription() << "\n";
srs56940a697312010-01-28 21:10:52 -0500227 cout.fill(' ');
228 } // if
229} // GPTPart::ShowDetails()
230
231// Blank (delete) a single partition
232void GPTPart::BlankPartition(void) {
srs56946699b012010-02-04 00:55:30 -0500233 uniqueGUID.Zero();
234 partitionType.Zero();
srs56940a697312010-01-28 21:10:52 -0500235 firstLBA = 0;
236 lastLBA = 0;
237 attributes = 0;
srs569464cbd172011-03-01 22:03:54 -0500238 memset(name, 0, NAME_SIZE);
srs56940a697312010-01-28 21:10:52 -0500239} // GPTPart::BlankPartition
240
241// Returns 1 if the two partitions overlap, 0 if they don't
242int GPTPart::DoTheyOverlap(const GPTPart & other) {
srs56940a697312010-01-28 21:10:52 -0500243 // Don't bother checking unless these are defined (both start and end points
244 // are 0 for undefined partitions, so just check the start points)
srs569464cbd172011-03-01 22:03:54 -0500245 return firstLBA && other.firstLBA &&
246 (firstLBA <= other.lastLBA) != (lastLBA < other.firstLBA);
srs56940a697312010-01-28 21:10:52 -0500247} // GPTPart::DoTheyOverlap()
248
srs56945a608532011-03-17 13:53:01 -0400249// Reverse the bytes of integral data types and of the UTF-16LE name;
250// used on big-endian systems.
srs56940a697312010-01-28 21:10:52 -0500251void GPTPart::ReversePartBytes(void) {
srs56945a608532011-03-17 13:53:01 -0400252 int i;
253
srs56940a697312010-01-28 21:10:52 -0500254 ReverseBytes(&firstLBA, 8);
255 ReverseBytes(&lastLBA, 8);
256 ReverseBytes(&attributes, 8);
srs56945a608532011-03-17 13:53:01 -0400257 for (i = 0; i < NAME_SIZE; i += 2)
258 ReverseBytes(name + i, 2);
srs56940a697312010-01-28 21:10:52 -0500259} // GPTPart::ReverseBytes()
260
261/****************************************
262 * Functions requiring user interaction *
263 ****************************************/
264
srs56946699b012010-02-04 00:55:30 -0500265// Change the type code on the partition. Also changes the name if the original
266// name is the generic one for the partition type.
srs56940a697312010-01-28 21:10:52 -0500267void GPTPart::ChangeType(void) {
srs56945a608532011-03-17 13:53:01 -0400268 string line;
srs569464cbd172011-03-01 22:03:54 -0500269 int changeName;
srs569482f3f0b2010-09-22 10:50:24 -0400270 PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
srs56940a697312010-01-28 21:10:52 -0500271
srs56945a608532011-03-17 13:53:01 -0400272 changeName = (GetDescription() == GetUTypeName());
srs569455d92612010-03-07 22:16:07 -0500273
srs56946699b012010-02-04 00:55:30 -0500274 cout << "Current type is '" << GetTypeName() << "'\n";
srs569482f3f0b2010-09-22 10:50:24 -0400275 do {
276 cout << "Hex code or GUID (L to show codes, Enter = 0700): ";
srs56945a608532011-03-17 13:53:01 -0400277 line = ReadString();
srs569482f3f0b2010-09-22 10:50:24 -0400278 if ((line[0] == 'L') || (line[0] == 'l')) {
srs56946699b012010-02-04 00:55:30 -0500279 partitionType.ShowAllTypes();
srs569482f3f0b2010-09-22 10:50:24 -0400280 } else {
srs56945a608532011-03-17 13:53:01 -0400281 if (line.length() == 0)
srs569482f3f0b2010-09-22 10:50:24 -0400282 tempType = 0x0700;
283 else
284 tempType = line;
285 } // if/else
286 } while (tempType == (GUIDData) "00000000-0000-0000-0000-000000000000");
287 partitionType = tempType;
srs56946699b012010-02-04 00:55:30 -0500288 cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
289 if (changeName) {
290 SetDefaultDescription();
291 } // if
srs56940a697312010-01-28 21:10:52 -0500292} // GPTPart::ChangeType()