resetting manifest requested domain to floor
[platform/upstream/gptfdisk.git] / gptpart.cc
1 //
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-2011
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
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.
14
15 #define __STDC_LIMIT_MACROS
16 #define __STDC_CONSTANT_MACROS
17
18 #ifdef USE_UTF16
19 #include <unicode/ustdio.h>
20 #else
21 #define UnicodeString string
22 #endif
23
24 #include <string.h>
25 #include <stdio.h>
26 #include <iostream>
27 #include "gptpart.h"
28 #include "attributes.h"
29
30 using namespace std;
31
32 GPTPart::GPTPart(void) {
33    partitionType.Zero();
34    uniqueGUID.Zero();
35    firstLBA = 0;
36    lastLBA = 0;
37    attributes = 0;
38    memset(name, 0, NAME_SIZE);
39 } // Default constructor
40
41 GPTPart::~GPTPart(void) {
42 } // destructor
43
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()
48
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()
54
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()
60
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 {
64    uint64_t length = 0;
65
66    if (firstLBA <= lastLBA)
67       length = lastLBA - firstLBA + UINT64_C(1);
68    return length;
69 } // GPTPart::GetLengthLBA()
70
71 #ifdef USE_UTF16
72 // Return partition's name field, converted to a Unicode string
73 UnicodeString GPTPart::GetDescription(void) {
74    return (UChar*) name;
75 } // GPTPart::GetDescription()
76 #else
77 // Return partition's name field, converted to a C++ ASCII string
78 string GPTPart::GetDescription(void) {
79    string theName;
80    int i = 0;
81
82    theName = "";
83    while ((i < NAME_SIZE) && (name[i] != '\0')) {
84       theName += name[i];
85       i+=2;
86    } // while
87    return theName;
88 } // GPTPart::GetDescription() (Windows version)
89 #endif
90
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()
96
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
99 // type.
100 void GPTPart::SetType(PartType t) {
101    if (GetDescription() == partitionType.UTypeName()) {
102       SetName(t.TypeName());
103    } // if
104    partitionType = t;
105 } // GPTPart::SetType()
106
107 #ifdef USE_UTF16
108 // Set the name for a partition to theName, using a C++-style string as
109 // input.
110 void GPTPart::SetName(const string & theName) {
111    SetName((UnicodeString) theName.c_str());
112 } // GPTPart::SetName()
113
114 // Set the name for a partition to theName, using a Unicode string as
115 // input.
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";
119    } else {
120       memset(name, 0, NAME_SIZE);
121       theName.extractBetween(0, NAME_SIZE / 2 - 1, (UChar*) name);
122    } // if/else
123 } // GPTPart::SetName()
124
125 #else
126
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
130 // for this.
131 void GPTPart::SetName(const string & theName) {
132    int i, length;
133
134    if (theName.length() < (NAME_SIZE / 2))
135       length = theName.length();
136    else
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
142 #endif
143
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()
149
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);
157    return *this;
158 } // assignment operator
159
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);
168    else
169       return (other.firstLBA < firstLBA);
170 } // GPTPart::operator<()
171
172 // Display summary information; does nothing if the partition is empty.
173 void GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
174    string sizeInIeee;
175    UnicodeString description;
176    size_t i;
177
178    if (firstLBA != 0) {
179       sizeInIeee = BytesToIeee(lastLBA - firstLBA + 1, blockSize);
180       cout.fill(' ');
181       cout.width(4);
182       cout << partNum + 1 << "  ";
183       cout.width(14);
184       cout << firstLBA << "  ";
185       cout.width(14);
186       cout << lastLBA  << "   ";
187       cout << BytesToIeee(lastLBA - firstLBA + 1, blockSize) << "  ";
188       if (sizeInIeee.length() < 10)
189          for (i = 0; i < 10 - sizeInIeee.length(); i++)
190             cout << " ";
191       cout.fill('0');
192       cout.width(4);
193       cout.setf(ios::uppercase);
194       cout << hex << partitionType.GetHexType() << "  " << dec;
195       cout.fill(' ');
196 #ifdef USE_UTF16
197       GetDescription().extractBetween(0, 23, description);
198       cout << description << "\n";
199 #else
200       cout << GetDescription().substr(0, 23) << "\n";
201 #endif
202       cout.fill(' ');
203    } // if
204 } // GPTPart::ShowSummary()
205
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) {
209    uint64_t size;
210
211    if (firstLBA != 0) {
212       cout << "Partition GUID code: " << partitionType;
213       cout << " (" << partitionType.TypeName() << ")\n";
214       cout << "Partition unique GUID: " << uniqueGUID << "\n";
215
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: ";
224       cout.fill('0');
225       cout.width(16);
226       cout << hex;
227       cout << attributes << "\n";
228       cout << dec;
229       cout << "Partition name: '" << GetDescription() << "'\n";
230       cout.fill(' ');
231    }  // if
232 } // GPTPart::ShowDetails()
233
234 // Blank (delete) a single partition
235 void GPTPart::BlankPartition(void) {
236    uniqueGUID.Zero();
237    partitionType.Zero();
238    firstLBA = 0;
239    lastLBA = 0;
240    attributes = 0;
241    memset(name, 0, NAME_SIZE);
242 } // GPTPart::BlankPartition
243
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()
251
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) {
255    int i;
256
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()
263
264 /****************************************
265  * Functions requiring user interaction *
266  ****************************************/
267
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) {
271    string line;
272    int changeName;
273    PartType tempType = (GUIDData) "00000000-0000-0000-0000-000000000000";
274
275    changeName = (GetDescription() == GetUTypeName());
276
277    cout << "Current type is '" << GetTypeName() << "'\n";
278    do {
279       cout << "Hex code or GUID (L to show codes, Enter = " << hex << DEFAULT_TYPE << dec << "): ";
280       line = ReadString();
281       if ((line[0] == 'L') || (line[0] == 'l')) {
282          partitionType.ShowAllTypes();
283       } else {
284          if (line.length() == 0)
285             tempType= DEFAULT_TYPE;
286          else
287             tempType = line;
288       } // if/else
289    } while (tempType == (GUIDData) "00000000-0000-0000-0000-000000000000");
290    partitionType = tempType;
291    cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
292    if (changeName) {
293       SetDefaultDescription();
294    } // if
295 } // GPTPart::ChangeType()