1cf200d32Sopenharmony_ci//
2cf200d32Sopenharmony_ci// C++ Implementation: gptpart
3cf200d32Sopenharmony_ci//
4cf200d32Sopenharmony_ci// Description: Class to implement a SINGLE GPT partition
5cf200d32Sopenharmony_ci//
6cf200d32Sopenharmony_ci//
7cf200d32Sopenharmony_ci// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009-2018
8cf200d32Sopenharmony_ci//
9cf200d32Sopenharmony_ci// Copyright: See COPYING file that comes with this distribution
10cf200d32Sopenharmony_ci//
11cf200d32Sopenharmony_ci//
12cf200d32Sopenharmony_ci// This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
13cf200d32Sopenharmony_ci// under the terms of the GNU GPL version 2, as detailed in the COPYING file.
14cf200d32Sopenharmony_ci
15cf200d32Sopenharmony_ci#define __STDC_LIMIT_MACROS
16cf200d32Sopenharmony_ci#ifndef __STDC_CONSTANT_MACROS
17cf200d32Sopenharmony_ci#define __STDC_CONSTANT_MACROS
18cf200d32Sopenharmony_ci#endif
19cf200d32Sopenharmony_ci
20cf200d32Sopenharmony_ci#include <string.h>
21cf200d32Sopenharmony_ci#include <stdio.h>
22cf200d32Sopenharmony_ci#include <iostream>
23cf200d32Sopenharmony_ci#include "gptpart.h"
24cf200d32Sopenharmony_ci#include "attributes.h"
25cf200d32Sopenharmony_ci#ifdef USE_UTF16
26cf200d32Sopenharmony_ci#include <unicode/ustdio.h>
27cf200d32Sopenharmony_ci#else
28cf200d32Sopenharmony_ci#define UnicodeString std::string
29cf200d32Sopenharmony_ci#endif
30cf200d32Sopenharmony_ci
31cf200d32Sopenharmony_ciusing namespace std;
32cf200d32Sopenharmony_ci
33cf200d32Sopenharmony_ciGPTPart::GPTPart(void) {
34cf200d32Sopenharmony_ci   partitionType.Zero();
35cf200d32Sopenharmony_ci   uniqueGUID.Zero();
36cf200d32Sopenharmony_ci   firstLBA = 0;
37cf200d32Sopenharmony_ci   lastLBA = 0;
38cf200d32Sopenharmony_ci   attributes = 0;
39cf200d32Sopenharmony_ci   memset(name, 0, NAME_SIZE * sizeof(name[0]) );
40cf200d32Sopenharmony_ci} // Default constructor
41cf200d32Sopenharmony_ci
42cf200d32Sopenharmony_ciGPTPart::GPTPart(const GPTPart & orig) {
43cf200d32Sopenharmony_ci   partitionType = orig.partitionType;
44cf200d32Sopenharmony_ci   uniqueGUID = orig.uniqueGUID;
45cf200d32Sopenharmony_ci   firstLBA = orig.firstLBA;
46cf200d32Sopenharmony_ci   lastLBA = orig.lastLBA;
47cf200d32Sopenharmony_ci   attributes = orig.attributes;
48cf200d32Sopenharmony_ci   memcpy(name, orig.name, NAME_SIZE * sizeof( name[ 0 ] ) );
49cf200d32Sopenharmony_ci} // Copy constructor
50cf200d32Sopenharmony_ci
51cf200d32Sopenharmony_ciGPTPart::~GPTPart(void) {
52cf200d32Sopenharmony_ci} // destructor
53cf200d32Sopenharmony_ci
54cf200d32Sopenharmony_ci// Return the gdisk-specific two-byte hex code for the partition
55cf200d32Sopenharmony_ciuint16_t GPTPart::GetHexType(void) const {
56cf200d32Sopenharmony_ci   return partitionType.GetHexType();
57cf200d32Sopenharmony_ci} // GPTPart::GetHexType()
58cf200d32Sopenharmony_ci
59cf200d32Sopenharmony_ci// Return a plain-text description of the partition type (e.g., "Linux/Windows
60cf200d32Sopenharmony_ci// data" or "Linux swap").
61cf200d32Sopenharmony_cistring GPTPart::GetTypeName(void) {
62cf200d32Sopenharmony_ci   return partitionType.TypeName();
63cf200d32Sopenharmony_ci} // GPTPart::GetNameType()
64cf200d32Sopenharmony_ci
65cf200d32Sopenharmony_ci#ifdef USE_UTF16
66cf200d32Sopenharmony_ci// Return a Unicode description of the partition type (e.g., "Linux/Windows
67cf200d32Sopenharmony_ci// data" or "Linux swap").
68cf200d32Sopenharmony_ciUnicodeString GPTPart::GetUTypeName(void) {
69cf200d32Sopenharmony_ci   return partitionType.UTypeName();
70cf200d32Sopenharmony_ci} // GPTPart::GetNameType()
71cf200d32Sopenharmony_ci#endif
72cf200d32Sopenharmony_ci
73cf200d32Sopenharmony_ci// Compute and return the partition's length (or 0 if the end is incorrectly
74cf200d32Sopenharmony_ci// set before the beginning).
75cf200d32Sopenharmony_ciuint64_t GPTPart::GetLengthLBA(void) const {
76cf200d32Sopenharmony_ci   uint64_t length = 0;
77cf200d32Sopenharmony_ci
78cf200d32Sopenharmony_ci   if (firstLBA <= lastLBA)
79cf200d32Sopenharmony_ci      length = lastLBA - firstLBA + UINT64_C(1);
80cf200d32Sopenharmony_ci   return length;
81cf200d32Sopenharmony_ci} // GPTPart::GetLengthLBA()
82cf200d32Sopenharmony_ci
83cf200d32Sopenharmony_ci#ifdef USE_UTF16
84cf200d32Sopenharmony_ci// Return partition's name field, converted to a Unicode string
85cf200d32Sopenharmony_ciUnicodeString GPTPart::GetDescription(void) {
86cf200d32Sopenharmony_ci   return (UChar*) name;
87cf200d32Sopenharmony_ci} // GPTPart::GetDescription()
88cf200d32Sopenharmony_ci#else
89cf200d32Sopenharmony_ci// Return partition's name field, converted to a C++ UTF-8 string
90cf200d32Sopenharmony_cistring GPTPart::GetDescription(void) {
91cf200d32Sopenharmony_ci   // convert name to utf32 then to utf8
92cf200d32Sopenharmony_ci   string utf8 ;
93cf200d32Sopenharmony_ci   size_t pos = 0 ;
94cf200d32Sopenharmony_ci   while ( ( pos < NAME_SIZE ) && ( name[ pos ] != 0 ) ) {
95cf200d32Sopenharmony_ci      uint16_t cp = name[ pos ++ ] ;
96cf200d32Sopenharmony_ci      // first to utf32
97cf200d32Sopenharmony_ci      uint32_t uni ;
98cf200d32Sopenharmony_ci      if ( cp < 0xd800 || cp > 0xdfff ) {
99cf200d32Sopenharmony_ci         uni = cp ;
100cf200d32Sopenharmony_ci      } // if
101cf200d32Sopenharmony_ci      else if ( cp < 0xdc00 ) {
102cf200d32Sopenharmony_ci         // lead surrogate
103cf200d32Sopenharmony_ci         uni = ( (uint32_t)( cp & 0x3ff ) ) << 10 ;
104cf200d32Sopenharmony_ci         if ( pos >= NAME_SIZE ) {
105cf200d32Sopenharmony_ci            // missing trail surrogate, name[] is invalid
106cf200d32Sopenharmony_ci            break ;
107cf200d32Sopenharmony_ci         } // if
108cf200d32Sopenharmony_ci         cp = name[ pos ++ ] ;
109cf200d32Sopenharmony_ci         if ( cp < 0xdc00 || cp > 0xdfff ) {
110cf200d32Sopenharmony_ci            // invalid trail surrogate, name[] is invalid
111cf200d32Sopenharmony_ci            break ;
112cf200d32Sopenharmony_ci         } // if
113cf200d32Sopenharmony_ci         // trail surrogate
114cf200d32Sopenharmony_ci         uni |= cp & 0x3ff ;
115cf200d32Sopenharmony_ci         uni += 0x10000 ;
116cf200d32Sopenharmony_ci      } // if
117cf200d32Sopenharmony_ci      else {
118cf200d32Sopenharmony_ci         // unexpected trail surrogate, name[] is invalid
119cf200d32Sopenharmony_ci         break ;
120cf200d32Sopenharmony_ci      } // if
121cf200d32Sopenharmony_ci      // then to utf8
122cf200d32Sopenharmony_ci      if ( uni < 0x80 ) {
123cf200d32Sopenharmony_ci         utf8 += (char) uni ;
124cf200d32Sopenharmony_ci      } // if
125cf200d32Sopenharmony_ci      else if ( uni < 0x800 ) {
126cf200d32Sopenharmony_ci         utf8 += (char) ( 0xc0 | ( uni >> 6 ) ) ;
127cf200d32Sopenharmony_ci         utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
128cf200d32Sopenharmony_ci      } // if
129cf200d32Sopenharmony_ci      else if ( uni < 0x10000 ) {
130cf200d32Sopenharmony_ci         utf8 += (char) ( 0xe0 | ( uni >> 12 ) ) ;
131cf200d32Sopenharmony_ci         utf8 += (char) ( 0x80 | ( ( uni >> 6 ) & 0x3f ) ) ;
132cf200d32Sopenharmony_ci         utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
133cf200d32Sopenharmony_ci      } // if
134cf200d32Sopenharmony_ci      else {
135cf200d32Sopenharmony_ci         utf8 += (char) ( 0xf0 | ( uni >> 18 ) ) ;
136cf200d32Sopenharmony_ci         utf8 += (char) ( 0xe0 | ( ( uni >> 12 ) & 0x3f ) ) ;
137cf200d32Sopenharmony_ci         utf8 += (char) ( 0x80 | ( ( uni >> 6 ) & 0x3f ) ) ;
138cf200d32Sopenharmony_ci         utf8 += (char) ( 0x80 | ( uni & 0x3f ) ) ;
139cf200d32Sopenharmony_ci      } // if
140cf200d32Sopenharmony_ci   }
141cf200d32Sopenharmony_ci   return utf8 ;
142cf200d32Sopenharmony_ci} // GPTPart::GetDescription(), UTF-8 version
143cf200d32Sopenharmony_ci#endif
144cf200d32Sopenharmony_ci
145cf200d32Sopenharmony_ci// Return 1 if the partition is in use
146cf200d32Sopenharmony_ciint GPTPart::IsUsed(void) {
147cf200d32Sopenharmony_ci   return (partitionType != GUIDData("0x00"));
148cf200d32Sopenharmony_ci} // GPTPart::IsUsed()
149cf200d32Sopenharmony_ci
150cf200d32Sopenharmony_ci// Returns MBR_SIZED_GOOD, MBR_SIZED_IFFY, or MBR_SIZED_BAD; see comments
151cf200d32Sopenharmony_ci// in header file for details.
152cf200d32Sopenharmony_ciint GPTPart::IsSizedForMBR(void) {
153cf200d32Sopenharmony_ci   int retval = MBR_SIZED_GOOD;
154cf200d32Sopenharmony_ci
155cf200d32Sopenharmony_ci   if ((firstLBA > UINT32_MAX) || ((lastLBA - firstLBA) > UINT32_MAX) || (firstLBA > lastLBA))
156cf200d32Sopenharmony_ci      retval = MBR_SIZED_BAD;
157cf200d32Sopenharmony_ci   else if (lastLBA > UINT32_MAX)
158cf200d32Sopenharmony_ci      retval = MBR_SIZED_IFFY;
159cf200d32Sopenharmony_ci
160cf200d32Sopenharmony_ci   return (retval);
161cf200d32Sopenharmony_ci} // GPTPart::IsSizedForMBR()
162cf200d32Sopenharmony_ci
163cf200d32Sopenharmony_ci// Set the type code to the specified one. Also changes the partition
164cf200d32Sopenharmony_ci// name *IF* the current name is the generic one for the current partition
165cf200d32Sopenharmony_ci// type.
166cf200d32Sopenharmony_civoid GPTPart::SetType(PartType t) {
167cf200d32Sopenharmony_ci#ifdef USE_UTF16
168cf200d32Sopenharmony_ci   if (GetDescription() == partitionType.UTypeName()) {
169cf200d32Sopenharmony_ci#else
170cf200d32Sopenharmony_ci   if (GetDescription() == partitionType.TypeName()) {
171cf200d32Sopenharmony_ci#endif
172cf200d32Sopenharmony_ci      SetName(t.TypeName());
173cf200d32Sopenharmony_ci   } // if
174cf200d32Sopenharmony_ci   partitionType = t;
175cf200d32Sopenharmony_ci} // GPTPart::SetType()
176cf200d32Sopenharmony_ci
177cf200d32Sopenharmony_ci#ifdef USE_UTF16
178cf200d32Sopenharmony_ci// Set the name for a partition to theName, using a C++-style string as
179cf200d32Sopenharmony_ci// input.
180cf200d32Sopenharmony_civoid GPTPart::SetName(const string & theName) {
181cf200d32Sopenharmony_ci   SetName((UnicodeString) theName.c_str());
182cf200d32Sopenharmony_ci} // GPTPart::SetName()
183cf200d32Sopenharmony_ci
184cf200d32Sopenharmony_ci// Set the name for a partition to theName, using a Unicode string as
185cf200d32Sopenharmony_ci// input.
186cf200d32Sopenharmony_civoid GPTPart::SetName(const UnicodeString & theName) {
187cf200d32Sopenharmony_ci   if (theName.isBogus()) {
188cf200d32Sopenharmony_ci      cerr << "Bogus UTF-16 name found in GPTPart::SetName()! Name not changed!\n";
189cf200d32Sopenharmony_ci   } else {
190cf200d32Sopenharmony_ci      memset(name, 0, NAME_SIZE * sizeof(name[0]) );
191cf200d32Sopenharmony_ci      theName.extractBetween(0, NAME_SIZE, (UChar*) name);
192cf200d32Sopenharmony_ci   } // if/else
193cf200d32Sopenharmony_ci} // GPTPart::SetName()
194cf200d32Sopenharmony_ci
195cf200d32Sopenharmony_ci#else
196cf200d32Sopenharmony_ci
197cf200d32Sopenharmony_ci// Set the name for a partition to theName. Note that theName is a
198cf200d32Sopenharmony_ci// standard C++-style ASCII string, although the GUID partition definition
199cf200d32Sopenharmony_ci// requires a UTF-16LE string. This function creates a simple-minded copy
200cf200d32Sopenharmony_ci// for this.
201cf200d32Sopenharmony_civoid GPTPart::SetName(const string & theName) {
202cf200d32Sopenharmony_ci   // convert utf8 to utf32 then to utf16le
203cf200d32Sopenharmony_ci   size_t len = theName.length() ;
204cf200d32Sopenharmony_ci   size_t pos = 0 ;
205cf200d32Sopenharmony_ci   for ( size_t i = 0 ; pos < NAME_SIZE && i < len ; ) {
206cf200d32Sopenharmony_ci      uint32_t uni ;
207cf200d32Sopenharmony_ci      uint8_t cp = theName[ i ++ ] ;
208cf200d32Sopenharmony_ci      int todo ;
209cf200d32Sopenharmony_ci      if ( cp < 0x80 ) {
210cf200d32Sopenharmony_ci         uni = cp ;
211cf200d32Sopenharmony_ci         todo = 0 ;
212cf200d32Sopenharmony_ci      } // if
213cf200d32Sopenharmony_ci      else if ( cp < 0xc0 || cp > 0xf7 ) {
214cf200d32Sopenharmony_ci         // invalid byte, theName is broken
215cf200d32Sopenharmony_ci         break ;
216cf200d32Sopenharmony_ci      } // if
217cf200d32Sopenharmony_ci      else if ( cp < 0xe0 ) {
218cf200d32Sopenharmony_ci         uni = cp & 0x1f ;
219cf200d32Sopenharmony_ci         todo = 1 ;
220cf200d32Sopenharmony_ci      } // if
221cf200d32Sopenharmony_ci      else if ( cp < 0xf0 ) {
222cf200d32Sopenharmony_ci         uni = cp & 0x0f ;
223cf200d32Sopenharmony_ci         todo = 2 ;
224cf200d32Sopenharmony_ci      } // if
225cf200d32Sopenharmony_ci      else {
226cf200d32Sopenharmony_ci         uni = cp & 0x7 ;
227cf200d32Sopenharmony_ci         todo = 3 ;
228cf200d32Sopenharmony_ci      } // if
229cf200d32Sopenharmony_ci      while ( todo > 0 ) {
230cf200d32Sopenharmony_ci         if ( i >= len ) {
231cf200d32Sopenharmony_ci            // missing continuation byte, theName is broken
232cf200d32Sopenharmony_ci            goto break_converter ;
233cf200d32Sopenharmony_ci         } // if
234cf200d32Sopenharmony_ci         cp = theName[ i ++ ] ;
235cf200d32Sopenharmony_ci         if ( cp > 0xbf || cp < 0x80 ) {
236cf200d32Sopenharmony_ci            // invalid continuation byte, theName is broken
237cf200d32Sopenharmony_ci            goto break_converter ;
238cf200d32Sopenharmony_ci         } // if
239cf200d32Sopenharmony_ci         uni <<= 6 ;
240cf200d32Sopenharmony_ci         uni |= cp & 0x3f ;
241cf200d32Sopenharmony_ci         todo -- ;
242cf200d32Sopenharmony_ci      } // while
243cf200d32Sopenharmony_ci      // then to utf16le
244cf200d32Sopenharmony_ci      if ( uni < 0x10000 ) {
245cf200d32Sopenharmony_ci         name[ pos ] = (uint16_t) uni ;
246cf200d32Sopenharmony_ci         pos ++ ;
247cf200d32Sopenharmony_ci      } // if
248cf200d32Sopenharmony_ci      else {
249cf200d32Sopenharmony_ci         if ( pos > NAME_SIZE - 2 ) {
250cf200d32Sopenharmony_ci             // not enough room for two surrogates, truncate
251cf200d32Sopenharmony_ci             break ;
252cf200d32Sopenharmony_ci         } // if
253cf200d32Sopenharmony_ci         uni -= 0x10000 ;
254cf200d32Sopenharmony_ci         name[ pos ] = (uint16_t)( uni >> 10 ) | 0xd800 ;
255cf200d32Sopenharmony_ci         pos ++ ;
256cf200d32Sopenharmony_ci         name[ pos ] = (uint16_t)( uni & 0x3ff ) | 0xdc00 ;
257cf200d32Sopenharmony_ci         pos ++ ;
258cf200d32Sopenharmony_ci      }
259cf200d32Sopenharmony_ci   } // for
260cf200d32Sopenharmony_ci   break_converter : ;
261cf200d32Sopenharmony_ci   // finally fill with zeroes
262cf200d32Sopenharmony_ci   while ( pos < NAME_SIZE ) {
263cf200d32Sopenharmony_ci      name[ pos ++ ] = 0 ;
264cf200d32Sopenharmony_ci   } // while
265cf200d32Sopenharmony_ci} // GPTPart::SetName(), UTF-8 version
266cf200d32Sopenharmony_ci#endif
267cf200d32Sopenharmony_ci
268cf200d32Sopenharmony_ci// Set the name for the partition based on the current GUID partition type
269cf200d32Sopenharmony_ci// code's associated name
270cf200d32Sopenharmony_civoid GPTPart::SetDefaultDescription(void) {
271cf200d32Sopenharmony_ci   SetName(partitionType.TypeName());
272cf200d32Sopenharmony_ci} // GPTPart::SetDefaultDescription()
273cf200d32Sopenharmony_ci
274cf200d32Sopenharmony_ciGPTPart & GPTPart::operator=(const GPTPart & orig) {
275cf200d32Sopenharmony_ci   partitionType = orig.partitionType;
276cf200d32Sopenharmony_ci   uniqueGUID = orig.uniqueGUID;
277cf200d32Sopenharmony_ci   firstLBA = orig.firstLBA;
278cf200d32Sopenharmony_ci   lastLBA = orig.lastLBA;
279cf200d32Sopenharmony_ci   attributes = orig.attributes;
280cf200d32Sopenharmony_ci   memcpy(name, orig.name, NAME_SIZE * sizeof( name[ 0 ] ) );
281cf200d32Sopenharmony_ci   return *this;
282cf200d32Sopenharmony_ci} // assignment operator
283cf200d32Sopenharmony_ci
284cf200d32Sopenharmony_ci// Compare the values, and return a bool result.
285cf200d32Sopenharmony_ci// Because this is intended for sorting and a firstLBA value of 0 denotes
286cf200d32Sopenharmony_ci// a partition that's not in use and so that should be sorted upwards,
287cf200d32Sopenharmony_ci// we return the opposite of the usual arithmetic result when either
288cf200d32Sopenharmony_ci// firstLBA value is 0.
289cf200d32Sopenharmony_cibool GPTPart::operator<(const GPTPart &other) const {
290cf200d32Sopenharmony_ci   if (firstLBA && other.firstLBA)
291cf200d32Sopenharmony_ci      return (firstLBA < other.firstLBA);
292cf200d32Sopenharmony_ci   else
293cf200d32Sopenharmony_ci      return (other.firstLBA < firstLBA);
294cf200d32Sopenharmony_ci} // GPTPart::operator<()
295cf200d32Sopenharmony_ci
296cf200d32Sopenharmony_ci// Display summary information; does nothing if the partition is empty.
297cf200d32Sopenharmony_civoid GPTPart::ShowSummary(int partNum, uint32_t blockSize) {
298cf200d32Sopenharmony_ci   string sizeInIeee;
299cf200d32Sopenharmony_ci   UnicodeString description;
300cf200d32Sopenharmony_ci   size_t i;
301cf200d32Sopenharmony_ci
302cf200d32Sopenharmony_ci   if (firstLBA != 0) {
303cf200d32Sopenharmony_ci      sizeInIeee = BytesToIeee(lastLBA - firstLBA + 1, blockSize);
304cf200d32Sopenharmony_ci      cout.fill(' ');
305cf200d32Sopenharmony_ci      cout.width(4);
306cf200d32Sopenharmony_ci      cout << partNum + 1 << "  ";
307cf200d32Sopenharmony_ci      cout.width(14);
308cf200d32Sopenharmony_ci      cout << firstLBA << "  ";
309cf200d32Sopenharmony_ci      cout.width(14);
310cf200d32Sopenharmony_ci      cout << lastLBA  << "   ";
311cf200d32Sopenharmony_ci      cout << sizeInIeee << "  ";
312cf200d32Sopenharmony_ci      if (sizeInIeee.length() < 10)
313cf200d32Sopenharmony_ci         for (i = 0; i < 10 - sizeInIeee.length(); i++)
314cf200d32Sopenharmony_ci            cout << " ";
315cf200d32Sopenharmony_ci      cout.fill('0');
316cf200d32Sopenharmony_ci      cout.width(4);
317cf200d32Sopenharmony_ci      cout.setf(ios::uppercase);
318cf200d32Sopenharmony_ci      cout << hex << partitionType.GetHexType() << "  " << dec;
319cf200d32Sopenharmony_ci      cout.fill(' ');
320cf200d32Sopenharmony_ci#ifdef USE_UTF16
321cf200d32Sopenharmony_ci      GetDescription().extractBetween(0, 23, description);
322cf200d32Sopenharmony_ci      cout << description << "\n";
323cf200d32Sopenharmony_ci#else
324cf200d32Sopenharmony_ci      string desc = GetDescription() ;
325cf200d32Sopenharmony_ci      size_t n = 0 ;
326cf200d32Sopenharmony_ci      size_t i = 0 ;
327cf200d32Sopenharmony_ci      size_t len = desc.length() ;
328cf200d32Sopenharmony_ci      while ( n < 22 && i < len ) {
329cf200d32Sopenharmony_ci         i ++ ;
330cf200d32Sopenharmony_ci         if ( i >= len ) {
331cf200d32Sopenharmony_ci            // short description
332cf200d32Sopenharmony_ci            break ;
333cf200d32Sopenharmony_ci         } // if
334cf200d32Sopenharmony_ci         // skip continuation bytes
335cf200d32Sopenharmony_ci         while ( i < len && ( ( desc[ i ] & 0xC0 ) == 0x80 ) ) {
336cf200d32Sopenharmony_ci             // utf8 continuation byte
337cf200d32Sopenharmony_ci             i ++ ;
338cf200d32Sopenharmony_ci         } // while
339cf200d32Sopenharmony_ci         n ++ ;
340cf200d32Sopenharmony_ci      } // while
341cf200d32Sopenharmony_ci      if ( i < len ) {
342cf200d32Sopenharmony_ci         n = 0 ;
343cf200d32Sopenharmony_ci         i = 0 ;
344cf200d32Sopenharmony_ci         // description is long we will truncate it
345cf200d32Sopenharmony_ci         while ( n < 19 && i < len ) {
346cf200d32Sopenharmony_ci            i ++ ;
347cf200d32Sopenharmony_ci            if ( i >= len ) {
348cf200d32Sopenharmony_ci               // should not happen
349cf200d32Sopenharmony_ci               break ;
350cf200d32Sopenharmony_ci            } // if
351cf200d32Sopenharmony_ci            // skip continuation bytes
352cf200d32Sopenharmony_ci            while ( i < len && ( ( desc[ i ] & 0xC0 ) == 0x80 ) ) {
353cf200d32Sopenharmony_ci                // utf8 continuation byte
354cf200d32Sopenharmony_ci                i ++ ;
355cf200d32Sopenharmony_ci            } // while
356cf200d32Sopenharmony_ci            n ++ ;
357cf200d32Sopenharmony_ci         } // while
358cf200d32Sopenharmony_ci      } // for
359cf200d32Sopenharmony_ci      cout << GetDescription().substr( 0 , i ) ;
360cf200d32Sopenharmony_ci      if ( i < len ) cout << "..." ;
361cf200d32Sopenharmony_ci      cout << "\n";
362cf200d32Sopenharmony_ci#endif
363cf200d32Sopenharmony_ci      cout.fill(' ');
364cf200d32Sopenharmony_ci   } // if
365cf200d32Sopenharmony_ci} // GPTPart::ShowSummary()
366cf200d32Sopenharmony_ci
367cf200d32Sopenharmony_ci// Show detailed partition information. Does nothing if the partition is
368cf200d32Sopenharmony_ci// empty (as determined by firstLBA being 0).
369cf200d32Sopenharmony_civoid GPTPart::ShowDetails(uint32_t blockSize) {
370cf200d32Sopenharmony_ci   uint64_t size;
371cf200d32Sopenharmony_ci
372cf200d32Sopenharmony_ci   if (firstLBA != 0) {
373cf200d32Sopenharmony_ci      cout << "Partition GUID code: " << partitionType;
374cf200d32Sopenharmony_ci      cout << " (" << partitionType.TypeName() << ")\n";
375cf200d32Sopenharmony_ci      cout << "Partition unique GUID: " << uniqueGUID << "\n";
376cf200d32Sopenharmony_ci
377cf200d32Sopenharmony_ci      cout << "First sector: " << firstLBA << " (at "
378cf200d32Sopenharmony_ci           << BytesToIeee(firstLBA, blockSize) << ")\n";
379cf200d32Sopenharmony_ci      cout << "Last sector: " << lastLBA << " (at "
380cf200d32Sopenharmony_ci           << BytesToIeee(lastLBA, blockSize) << ")\n";
381cf200d32Sopenharmony_ci      size = (lastLBA - firstLBA + 1);
382cf200d32Sopenharmony_ci      cout << "Partition size: " << size << " sectors ("
383cf200d32Sopenharmony_ci           << BytesToIeee(size, blockSize) << ")\n";
384cf200d32Sopenharmony_ci      cout << "Attribute flags: ";
385cf200d32Sopenharmony_ci      cout.fill('0');
386cf200d32Sopenharmony_ci      cout.width(16);
387cf200d32Sopenharmony_ci      cout << hex;
388cf200d32Sopenharmony_ci      cout << attributes << "\n";
389cf200d32Sopenharmony_ci      cout << dec;
390cf200d32Sopenharmony_ci      cout << "Partition name: '" << GetDescription() << "'\n";
391cf200d32Sopenharmony_ci      cout.fill(' ');
392cf200d32Sopenharmony_ci   }  // if
393cf200d32Sopenharmony_ci} // GPTPart::ShowDetails()
394cf200d32Sopenharmony_ci
395cf200d32Sopenharmony_ci// Blank (delete) a single partition
396cf200d32Sopenharmony_civoid GPTPart::BlankPartition(void) {
397cf200d32Sopenharmony_ci   uniqueGUID.Zero();
398cf200d32Sopenharmony_ci   partitionType.Zero();
399cf200d32Sopenharmony_ci   firstLBA = 0;
400cf200d32Sopenharmony_ci   lastLBA = 0;
401cf200d32Sopenharmony_ci   attributes = 0;
402cf200d32Sopenharmony_ci   memset(name, 0, NAME_SIZE * sizeof( name[0]) );
403cf200d32Sopenharmony_ci} // GPTPart::BlankPartition
404cf200d32Sopenharmony_ci
405cf200d32Sopenharmony_ci// Returns 1 if the two partitions overlap, 0 if they don't
406cf200d32Sopenharmony_ciint GPTPart::DoTheyOverlap(const GPTPart & other) {
407cf200d32Sopenharmony_ci   // Don't bother checking unless these are defined (both start and end points
408cf200d32Sopenharmony_ci   // are 0 for undefined partitions, so just check the start points)
409cf200d32Sopenharmony_ci   return firstLBA && other.firstLBA &&
410cf200d32Sopenharmony_ci          (firstLBA <= other.lastLBA) != (lastLBA < other.firstLBA);
411cf200d32Sopenharmony_ci} // GPTPart::DoTheyOverlap()
412cf200d32Sopenharmony_ci
413cf200d32Sopenharmony_ci// Reverse the bytes of integral data types and of the UTF-16LE name;
414cf200d32Sopenharmony_ci// used on big-endian systems.
415cf200d32Sopenharmony_civoid GPTPart::ReversePartBytes(void) {
416cf200d32Sopenharmony_ci   ReverseBytes(&firstLBA, 8);
417cf200d32Sopenharmony_ci   ReverseBytes(&lastLBA, 8);
418cf200d32Sopenharmony_ci   ReverseBytes(&attributes, 8);
419cf200d32Sopenharmony_ci   ReverseNameBytes();
420cf200d32Sopenharmony_ci} // GPTPart::ReversePartBytes()
421cf200d32Sopenharmony_ci
422cf200d32Sopenharmony_civoid GPTPart::ReverseNameBytes(void) {
423cf200d32Sopenharmony_ci   int i;
424cf200d32Sopenharmony_ci
425cf200d32Sopenharmony_ci   for (i = 0; i < NAME_SIZE; i ++ )
426cf200d32Sopenharmony_ci      ReverseBytes(name + i, 2);
427cf200d32Sopenharmony_ci} // GPTPart::ReverseNameBytes()
428cf200d32Sopenharmony_ci
429cf200d32Sopenharmony_ci/****************************************
430cf200d32Sopenharmony_ci * Functions requiring user interaction *
431cf200d32Sopenharmony_ci ****************************************/
432cf200d32Sopenharmony_ci
433cf200d32Sopenharmony_ci// Change the type code on the partition. Also changes the name if the original
434cf200d32Sopenharmony_ci// name is the generic one for the partition type.
435cf200d32Sopenharmony_civoid GPTPart::ChangeType(void) {
436cf200d32Sopenharmony_ci   string line;
437cf200d32Sopenharmony_ci   int changeName;
438cf200d32Sopenharmony_ci   PartType tempType = PartType::unusedPartType;
439cf200d32Sopenharmony_ci
440cf200d32Sopenharmony_ci#ifdef USE_UTF16
441cf200d32Sopenharmony_ci   changeName = (GetDescription() == GetUTypeName());
442cf200d32Sopenharmony_ci#else
443cf200d32Sopenharmony_ci   changeName = (GetDescription() == GetTypeName());
444cf200d32Sopenharmony_ci#endif
445cf200d32Sopenharmony_ci
446cf200d32Sopenharmony_ci   cout << "Current type is " << hex << GetHexType() << dec << " (" << GetTypeName() << ")\n";
447cf200d32Sopenharmony_ci   do {
448cf200d32Sopenharmony_ci      cout << "Hex code or GUID (L to show codes, Enter = " << hex << GetHexType() << dec << "): ";
449cf200d32Sopenharmony_ci      line = ReadString();
450cf200d32Sopenharmony_ci      if ((line[0] == 'L') || (line[0] == 'l')) {
451cf200d32Sopenharmony_ci         partitionType.ShowAllTypes();
452cf200d32Sopenharmony_ci      } else {
453cf200d32Sopenharmony_ci         if (line.length() == 0)
454cf200d32Sopenharmony_ci            tempType = GetHexType();
455cf200d32Sopenharmony_ci         else
456cf200d32Sopenharmony_ci            tempType = line;
457cf200d32Sopenharmony_ci      } // if/else
458cf200d32Sopenharmony_ci   } while (tempType == PartType::unusedPartType);
459cf200d32Sopenharmony_ci   partitionType = tempType;
460cf200d32Sopenharmony_ci   cout << "Changed type of partition to '" << partitionType.TypeName() << "'\n";
461cf200d32Sopenharmony_ci   if (changeName) {
462cf200d32Sopenharmony_ci      SetDefaultDescription();
463cf200d32Sopenharmony_ci   } // if
464cf200d32Sopenharmony_ci} // GPTPart::ChangeType()
465