2 // C++ Implementation: gptpart
4 // Description: Class to implement a SINGLE GPT partition
7 // Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009-2011
9 // Copyright: See COPYING file that comes with this distribution
12 // 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.
15 #define __STDC_LIMIT_MACROS
16 #define __STDC_CONSTANT_MACROS
19 #include <unicode/ustdio.h>
21 #define UnicodeString string
28 #include "attributes.h"
32 GPTPart::GPTPart(void) {
38 memset(name, 0, NAME_SIZE);
39 } // Default constructor
41 GPTPart::~GPTPart(void) {
44 // Return the gdisk-specific two-byte hex code for the partition
45 uint16_t GPTPart::GetHexType(void) const {
46 return partitionType.GetHexType();
47 } // GPTPart::GetHexType()
49 // Return a plain-text description of the partition type (e.g., "Linux/Windows
50 // data" or "Linux swap").
51 string GPTPart::GetTypeName(void) {
52 return partitionType.TypeName();
53 } // GPTPart::GetNameType()
55 // Return a Unicode description of the partition type (e.g., "Linux/Windows
56 // data" or "Linux swap").
57 UnicodeString GPTPart::GetUTypeName(void) {
58 return partitionType.UTypeName();
59 } // GPTPart::GetNameType()
61 // Compute and return the partition's length (or 0 if the end is incorrectly
62 // set before the beginning).
63 uint64_t GPTPart::GetLengthLBA(void) const {
66 if (firstLBA <= lastLBA)
67 length = lastLBA - firstLBA + UINT64_C(1);
69 } // GPTPart::GetLengthLBA()
72 // Return partition's name field, converted to a Unicode string
73 UnicodeString GPTPart::GetDescription(void) {
75 } // GPTPart::GetDescription()
77 // Return partition's name field, converted to a C++ ASCII string
78 string GPTPart::GetDescription(void) {
83 while ((i < NAME_SIZE) && (name[i] != '\0')) {
88 } // GPTPart::GetDescription() (Windows version)
91 // Return 1 if the partition is in use
92 int GPTPart::IsUsed(void) {
93 return (partitionType != GUIDData("0x00"));
94 // return (firstLBA != UINT64_C(0));
95 } // GPTPart::IsUsed()
97 // Set the type code to the specified one. Also changes the partition
98 // name *IF* the current name is the generic one for the current partition
100 void GPTPart::SetType(PartType t) {
101 if (GetDescription() == partitionType.UTypeName()) {
102 SetName(t.TypeName());
105 } // GPTPart::SetType()
108 // Set the name for a partition to theName, using a C++-style string as
110 void GPTPart::SetName(const string & theName) {
111 SetName((UnicodeString) theName.c_str());
112 } // GPTPart::SetName()
114 // Set the name for a partition to theName, using a Unicode string as
116 void GPTPart::SetName(const UnicodeString & theName) {
117 if (theName.isBogus()) {
118 cerr << "Bogus UTF-16 name found in GPTPart::SetName()! Name not changed!\n";
120 memset(name, 0, NAME_SIZE);
121 theName.extractBetween(0, NAME_SIZE / 2 - 1, (UChar*) name);
123 } // GPTPart::SetName()
127 // Set the name for a partition to theName. Note that theName is a
128 // standard C++-style ASCII string, although the GUID partition definition
129 // requires a UTF-16LE string. This function creates a simple-minded copy
131 void GPTPart::SetName(const string & theName) {
134 if (theName.length() < (NAME_SIZE / 2))
135 length = theName.length();
137 length = NAME_SIZE / 2;
138 memset(name, 0, NAME_SIZE);
139 for (i = 0; i < length; i++)
140 name[i * 2] = theName[i];
141 } // GPTPart::SetName(), Windows version
144 // Set the name for the partition based on the current GUID partition type
145 // code's associated name
146 void GPTPart::SetDefaultDescription(void) {
147 SetName(partitionType.TypeName());
148 } // GPTPart::SetDefaultDescription()
150 GPTPart & GPTPart::operator=(const GPTPart & orig) {
151 partitionType = orig.partitionType;
152 uniqueGUID = orig.uniqueGUID;
153 firstLBA = orig.firstLBA;
154 lastLBA = orig.lastLBA;
155 attributes = orig.attributes;
156 memcpy(name, orig.name, NAME_SIZE);
158 } // assignment operator
160 // Compare the values, and return a bool result.
161 // Because this is intended for sorting and a firstLBA value of 0 denotes
162 // a partition that's not in use and so that should be sorted upwards,
163 // we return the opposite of the usual arithmetic result when either
164 // firstLBA value is 0.
165 bool GPTPart::operator<(const GPTPart &other) const {
166 if (firstLBA && other.firstLBA)
167 return (firstLBA < other.firstLBA);
169 return (other.firstLBA < firstLBA);
170 } // GPTPart::operator<()
172 // Display summary information; does nothing if the partition is empty.
173 void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
175 UnicodeString description;
179 sizeInIeee = BytesToIeee(lastLBA - firstLBA + 1, blockSize);
182 cout << partNum + 1 << " ";
184 cout << firstLBA << " ";
186 cout << lastLBA << " ";
187 cout << BytesToIeee(lastLBA - firstLBA + 1, blockSize) << " ";
188 if (sizeInIeee.length() < 10)
189 for (i = 0; i < 10 - sizeInIeee.length(); i++)
193 cout.setf(ios::uppercase);
194 cout << hex << partitionType.GetHexType() << " " << dec;
197 GetDescription().extractBetween(0, 23, description);
198 cout << description << "\n";
200 cout << GetDescription().substr(0, 23) << "\n";
204 } // GPTPart::ShowSummary()
206 // Show detailed partition information. Does nothing if the partition is
207 // empty (as determined by firstLBA being 0).
208 void GPTPart::ShowDetails(uint32_t blockSize) {
212 cout << "Partition GUID code: " << partitionType;
213 cout << " (" << partitionType.TypeName() << ")\n";
214 cout << "Partition unique GUID: " << uniqueGUID << "\n";
216 cout << "First sector: " << firstLBA << " (at "
217 << BytesToIeee(firstLBA, blockSize) << ")\n";
218 cout << "Last sector: " << lastLBA << " (at "
219 << BytesToIeee(lastLBA, blockSize) << ")\n";
220 size = (lastLBA - firstLBA + 1);
221 cout << "Partition size: " << size << " sectors ("
222 << BytesToIeee(size, blockSize) << ")\n";
223 cout << "Attribute flags: ";
227 cout << attributes << "\n";
229 cout << "Partition name: '" << GetDescription() << "'\n";
232 } // GPTPart::ShowDetails()
234 // Blank (delete) a single partition
235 void GPTPart::BlankPartition(void) {
237 partitionType.Zero();
241 memset(name, 0, NAME_SIZE);
242 } // GPTPart::BlankPartition
244 // Returns 1 if the two partitions overlap, 0 if they don't
245 int GPTPart::DoTheyOverlap(const GPTPart & other) {
246 // Don't bother checking unless these are defined (both start and end points
247 // are 0 for undefined partitions, so just check the start points)
248 return firstLBA && other.firstLBA &&
249 (firstLBA <= other.lastLBA) != (lastLBA < other.firstLBA);
250 } // GPTPart::DoTheyOverlap()
252 // Reverse the bytes of integral data types and of the UTF-16LE name;
253 // used on big-endian systems.
254 void GPTPart::ReversePartBytes(void) {
257 ReverseBytes(&firstLBA, 8);
258 ReverseBytes(&lastLBA, 8);
259 ReverseBytes(&attributes, 8);
260 for (i = 0; i < NAME_SIZE; i += 2)
261 ReverseBytes(name + i, 2);
262 } // GPTPart::ReverseBytes()
264 /****************************************
265 * Functions requiring user interaction *
266 ****************************************/
268 // Change the type code on the partition. Also changes the name if the original
269 // name is the generic one for the partition type.
270 void GPTPart::ChangeType(void) {
273 PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
275 changeName = (GetDescription() == GetUTypeName());
277 cout << "Current type is '" << GetTypeName() << "'\n";
279 cout << "Hex code or GUID (L to show codes, Enter = " << hex << DEFAULT_TYPE << dec << "): ";
281 if ((line[0] == 'L') || (line[0] == 'l')) {
282 partitionType.ShowAllTypes();
284 if (line.length() == 0)
285 tempType= DEFAULT_TYPE;
289 } while (tempType == (GUIDData) "00000000-0000-0000-0000-000000000000");
290 partitionType = tempType;
291 cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
293 SetDefaultDescription();
295 } // GPTPart::ChangeType()