1cf200d32Sopenharmony_ci// support.cc 2cf200d32Sopenharmony_ci// Non-class support functions for gdisk program. 3cf200d32Sopenharmony_ci// Primarily by Rod Smith, February 2009, but with a few functions 4cf200d32Sopenharmony_ci// copied from other sources (see attributions below). 5cf200d32Sopenharmony_ci 6cf200d32Sopenharmony_ci/* This program is copyright (c) 2009-2024 by Roderick W. Smith. It is distributed 7cf200d32Sopenharmony_ci under the terms of the GNU GPL version 2, as detailed in the COPYING file. */ 8cf200d32Sopenharmony_ci 9cf200d32Sopenharmony_ci#define __STDC_LIMIT_MACROS 10cf200d32Sopenharmony_ci#ifndef __STDC_CONSTANT_MACROS 11cf200d32Sopenharmony_ci#define __STDC_CONSTANT_MACROS 12cf200d32Sopenharmony_ci#endif 13cf200d32Sopenharmony_ci#ifndef __STDC_FORMAT_MACROS 14cf200d32Sopenharmony_ci#define __STDC_FORMAT_MACROS 15cf200d32Sopenharmony_ci#endif 16cf200d32Sopenharmony_ci 17cf200d32Sopenharmony_ci#include <inttypes.h> 18cf200d32Sopenharmony_ci#include <stdio.h> 19cf200d32Sopenharmony_ci#include <stdint.h> 20cf200d32Sopenharmony_ci#include <errno.h> 21cf200d32Sopenharmony_ci#include <fcntl.h> 22cf200d32Sopenharmony_ci#include <string.h> 23cf200d32Sopenharmony_ci#include <sys/stat.h> 24cf200d32Sopenharmony_ci#include <string> 25cf200d32Sopenharmony_ci#include <cctype> 26cf200d32Sopenharmony_ci#include <algorithm> 27cf200d32Sopenharmony_ci#include <iostream> 28cf200d32Sopenharmony_ci#include <sstream> 29cf200d32Sopenharmony_ci#include "support.h" 30cf200d32Sopenharmony_ci 31cf200d32Sopenharmony_ci#include <sys/types.h> 32cf200d32Sopenharmony_ci 33cf200d32Sopenharmony_ci// As of 1/2010, BLKPBSZGET is very new, so I'm explicitly defining it if 34cf200d32Sopenharmony_ci// it's not already defined. This should become unnecessary in the future. 35cf200d32Sopenharmony_ci// Note that this is a Linux-only ioctl.... 36cf200d32Sopenharmony_ci#ifndef BLKPBSZGET 37cf200d32Sopenharmony_ci#define BLKPBSZGET _IO(0x12,123) 38cf200d32Sopenharmony_ci#endif 39cf200d32Sopenharmony_ci 40cf200d32Sopenharmony_ciusing namespace std; 41cf200d32Sopenharmony_ci 42cf200d32Sopenharmony_ci// Reads a string from stdin, returning it as a C++-style string. 43cf200d32Sopenharmony_ci// Note that the returned string will NOT include the carriage return 44cf200d32Sopenharmony_ci// entered by the user. 45cf200d32Sopenharmony_ci#ifdef EFI 46cf200d32Sopenharmony_ciextern int __sscanf( const char * str , const char * format , ... ) ; 47cf200d32Sopenharmony_cistring ReadString(void) { 48cf200d32Sopenharmony_ci string inString; 49cf200d32Sopenharmony_ci char efiString[256]; 50cf200d32Sopenharmony_ci int stringLength; 51cf200d32Sopenharmony_ci 52cf200d32Sopenharmony_ci if (fgets(efiString, 255, stdin) != NULL) { 53cf200d32Sopenharmony_ci stringLength = strlen(efiString); 54cf200d32Sopenharmony_ci if ((stringLength > 0) && (efiString[stringLength - 1] == '\n')) 55cf200d32Sopenharmony_ci efiString[stringLength - 1] = '\0'; 56cf200d32Sopenharmony_ci inString = efiString; 57cf200d32Sopenharmony_ci } else { 58cf200d32Sopenharmony_ci inString = ""; 59cf200d32Sopenharmony_ci } 60cf200d32Sopenharmony_ci return inString; 61cf200d32Sopenharmony_ci} // ReadString() 62cf200d32Sopenharmony_ci#else 63cf200d32Sopenharmony_cistring ReadString(void) { 64cf200d32Sopenharmony_ci string inString; 65cf200d32Sopenharmony_ci 66cf200d32Sopenharmony_ci cout << flush; 67cf200d32Sopenharmony_ci getline(cin, inString); 68cf200d32Sopenharmony_ci if (!cin.good()) 69cf200d32Sopenharmony_ci exit(5); 70cf200d32Sopenharmony_ci return inString; 71cf200d32Sopenharmony_ci} // ReadString() 72cf200d32Sopenharmony_ci#endif 73cf200d32Sopenharmony_ci 74cf200d32Sopenharmony_ci// Get a numeric value from the user, between low and high (inclusive). 75cf200d32Sopenharmony_ci// Keeps looping until the user enters a value within that range. 76cf200d32Sopenharmony_ci// If user provides no input, def (default value) is returned. 77cf200d32Sopenharmony_ci// (If def is outside of the low-high range, an explicit response 78cf200d32Sopenharmony_ci// is required.) 79cf200d32Sopenharmony_ciuint64_t GetNumber(uint64_t low, uint64_t high, uint64_t def, const string & prompt) { 80cf200d32Sopenharmony_ci uint64_t response, num; 81cf200d32Sopenharmony_ci char line[255]; 82cf200d32Sopenharmony_ci 83cf200d32Sopenharmony_ci if (low != high) { // bother only if low and high differ... 84cf200d32Sopenharmony_ci do { 85cf200d32Sopenharmony_ci cout << prompt << flush; 86cf200d32Sopenharmony_ci cin.getline(line, 255); 87cf200d32Sopenharmony_ci if (!cin.good()) 88cf200d32Sopenharmony_ci exit(5); 89cf200d32Sopenharmony_ci num = sscanf(line, "%" PRIu64, &response); 90cf200d32Sopenharmony_ci if (num == 1) { // user provided a response 91cf200d32Sopenharmony_ci if ((response < low) || (response > high)) 92cf200d32Sopenharmony_ci cout << "Value out of range\n"; 93cf200d32Sopenharmony_ci } else { // user hit enter; return default 94cf200d32Sopenharmony_ci response = def; 95cf200d32Sopenharmony_ci } // if/else 96cf200d32Sopenharmony_ci } while ((response < low) || (response > high)); 97cf200d32Sopenharmony_ci } else { // low == high, so return this value 98cf200d32Sopenharmony_ci cout << "Using " << low << "\n"; 99cf200d32Sopenharmony_ci response = low; 100cf200d32Sopenharmony_ci } // else 101cf200d32Sopenharmony_ci return (response); 102cf200d32Sopenharmony_ci} // GetNumber() 103cf200d32Sopenharmony_ci 104cf200d32Sopenharmony_ci// Gets a Y/N response (and converts lowercase to uppercase) 105cf200d32Sopenharmony_cichar GetYN(void) { 106cf200d32Sopenharmony_ci char response; 107cf200d32Sopenharmony_ci string line; 108cf200d32Sopenharmony_ci bool again = 0 ; 109cf200d32Sopenharmony_ci 110cf200d32Sopenharmony_ci do { 111cf200d32Sopenharmony_ci if ( again ) { cout << "Your option? " ; } 112cf200d32Sopenharmony_ci again = 1 ; 113cf200d32Sopenharmony_ci cout << "(Y/N): " << flush; 114cf200d32Sopenharmony_ci line = ReadString(); 115cf200d32Sopenharmony_ci response = toupper(line[0]); 116cf200d32Sopenharmony_ci } while ((response != 'Y') && (response != 'N')); 117cf200d32Sopenharmony_ci return response; 118cf200d32Sopenharmony_ci} // GetYN(void) 119cf200d32Sopenharmony_ci 120cf200d32Sopenharmony_ci// Convert an IEEE-1541-2002 value (K, M, G, T, P, or E) to its equivalent in 121cf200d32Sopenharmony_ci// number of sectors. If no units are appended, interprets as the number 122cf200d32Sopenharmony_ci// of sectors; otherwise, interprets as number of specified units and 123cf200d32Sopenharmony_ci// converts to sectors. For instance, with 512-byte sectors, "1K" converts 124cf200d32Sopenharmony_ci// to 2. If value includes a "+", adds low and subtracts 1; if inValue 125cf200d32Sopenharmony_ci// inclues a "-", subtracts from high. If IeeeValue is empty, returns def. 126cf200d32Sopenharmony_ci// Returns final sector value. In case inValue is invalid, returns 0 (a 127cf200d32Sopenharmony_ci// sector value that's always in use on GPT and therefore invalid); and if 128cf200d32Sopenharmony_ci// inValue works out to something outside the range low-high, returns the 129cf200d32Sopenharmony_ci// computed value; the calling function is responsible for checking the 130cf200d32Sopenharmony_ci// validity of this value. 131cf200d32Sopenharmony_ci// If inValue contains a decimal number (e.g., "9.5G"), quietly truncate it 132cf200d32Sopenharmony_ci// (to "9G" in this example). 133cf200d32Sopenharmony_ci// NOTE: There's a difference in how GCC and VC++ treat oversized values 134cf200d32Sopenharmony_ci// (say, "999999999999999999999") read via the ">>" operator; GCC turns 135cf200d32Sopenharmony_ci// them into the maximum value for the type, whereas VC++ turns them into 136cf200d32Sopenharmony_ci// 0 values. The result is that IeeeToInt() returns UINT64_MAX when 137cf200d32Sopenharmony_ci// compiled with GCC (and so the value is rejected), whereas when VC++ 138cf200d32Sopenharmony_ci// is used, the default value is returned. 139cf200d32Sopenharmony_ciuint64_t IeeeToInt(string inValue, uint64_t sSize, uint64_t low, uint64_t high, uint32_t sectorAlignment, uint64_t def) { 140cf200d32Sopenharmony_ci uint64_t response = def, bytesPerUnit, mult = 1, divide = 1; 141cf200d32Sopenharmony_ci size_t foundAt = 0; 142cf200d32Sopenharmony_ci char suffix = ' ', plusFlag = ' '; 143cf200d32Sopenharmony_ci string suffixes = "KMGTPE"; 144cf200d32Sopenharmony_ci int badInput = 0; // flag bad input; once this goes to 1, other values are irrelevant 145cf200d32Sopenharmony_ci 146cf200d32Sopenharmony_ci if (sSize == 0) { 147cf200d32Sopenharmony_ci sSize = SECTOR_SIZE; 148cf200d32Sopenharmony_ci cerr << "Bug: Sector size invalid in IeeeToInt()!\n"; 149cf200d32Sopenharmony_ci } // if 150cf200d32Sopenharmony_ci 151cf200d32Sopenharmony_ci // Remove leading spaces, if present 152cf200d32Sopenharmony_ci while (inValue[0] == ' ') 153cf200d32Sopenharmony_ci inValue.erase(0, 1); 154cf200d32Sopenharmony_ci 155cf200d32Sopenharmony_ci // If present, flag and remove leading plus or minus sign 156cf200d32Sopenharmony_ci if ((inValue[0] == '+') || (inValue[0] == '-')) { 157cf200d32Sopenharmony_ci plusFlag = inValue[0]; 158cf200d32Sopenharmony_ci inValue.erase(0, 1); 159cf200d32Sopenharmony_ci } // if 160cf200d32Sopenharmony_ci 161cf200d32Sopenharmony_ci // Extract numeric response and, if present, suffix 162cf200d32Sopenharmony_ci istringstream inString(inValue); 163cf200d32Sopenharmony_ci if (((inString.peek() < '0') || (inString.peek() > '9')) && (inString.peek() != -1)) 164cf200d32Sopenharmony_ci badInput = 1; 165cf200d32Sopenharmony_ci inString >> response >> suffix; 166cf200d32Sopenharmony_ci suffix = toupper(suffix); 167cf200d32Sopenharmony_ci foundAt = suffixes.find(suffix); 168cf200d32Sopenharmony_ci // If suffix is invalid, try to find a valid one. Done because users 169cf200d32Sopenharmony_ci // sometimes enter decimal numbers; when they do, suffix becomes 170cf200d32Sopenharmony_ci // '.', and we need to truncate the number and find the real suffix. 171cf200d32Sopenharmony_ci while (foundAt > (suffixes.length() - 1) && inString.peek() != -1) { 172cf200d32Sopenharmony_ci inString >> suffix; 173cf200d32Sopenharmony_ci foundAt = suffixes.find(suffix); 174cf200d32Sopenharmony_ci suffix = toupper(suffix); 175cf200d32Sopenharmony_ci } 176cf200d32Sopenharmony_ci // If no response, or if response == 0, use default (def) 177cf200d32Sopenharmony_ci if ((inValue.length() == 0) || (response == 0)) { 178cf200d32Sopenharmony_ci response = def; 179cf200d32Sopenharmony_ci suffix = ' '; 180cf200d32Sopenharmony_ci plusFlag = ' '; 181cf200d32Sopenharmony_ci } // if 182cf200d32Sopenharmony_ci 183cf200d32Sopenharmony_ci // Find multiplication and division factors for the suffix 184cf200d32Sopenharmony_ci if (foundAt != string::npos) { 185cf200d32Sopenharmony_ci bytesPerUnit = UINT64_C(1) << (10 * (foundAt + 1)); 186cf200d32Sopenharmony_ci mult = bytesPerUnit / sSize; 187cf200d32Sopenharmony_ci divide = sSize / bytesPerUnit; 188cf200d32Sopenharmony_ci } // if 189cf200d32Sopenharmony_ci 190cf200d32Sopenharmony_ci // Adjust response based on multiplier and plus flag, if present 191cf200d32Sopenharmony_ci if (mult > 1) { 192cf200d32Sopenharmony_ci if (response > (UINT64_MAX / mult)) 193cf200d32Sopenharmony_ci badInput = 1; 194cf200d32Sopenharmony_ci else 195cf200d32Sopenharmony_ci response *= mult; 196cf200d32Sopenharmony_ci } else if (divide > 1) { 197cf200d32Sopenharmony_ci response /= divide; 198cf200d32Sopenharmony_ci } // if/elseif 199cf200d32Sopenharmony_ci 200cf200d32Sopenharmony_ci if (plusFlag == '+') { 201cf200d32Sopenharmony_ci // Recompute response based on low part of range (if default is within 202cf200d32Sopenharmony_ci // sectorAlignment sectors of high, which should be the case when 203cf200d32Sopenharmony_ci // prompting for the end of a range) or the defaut value (if default is 204cf200d32Sopenharmony_ci // further away from the high value, which should be the case for the 205cf200d32Sopenharmony_ci // first sector of a partition). 206cf200d32Sopenharmony_ci if ((high - def) < sectorAlignment) { 207cf200d32Sopenharmony_ci if (response > 0) 208cf200d32Sopenharmony_ci response--; 209cf200d32Sopenharmony_ci if (response > (UINT64_MAX - low)) 210cf200d32Sopenharmony_ci badInput = 1; 211cf200d32Sopenharmony_ci else 212cf200d32Sopenharmony_ci response = response + low; 213cf200d32Sopenharmony_ci } else { 214cf200d32Sopenharmony_ci if (response > (UINT64_MAX - def)) 215cf200d32Sopenharmony_ci badInput = 1; 216cf200d32Sopenharmony_ci else 217cf200d32Sopenharmony_ci response = response + def; 218cf200d32Sopenharmony_ci } // if/else 219cf200d32Sopenharmony_ci } else if (plusFlag == '-') { 220cf200d32Sopenharmony_ci if (response > high) 221cf200d32Sopenharmony_ci badInput = 1; 222cf200d32Sopenharmony_ci else 223cf200d32Sopenharmony_ci response = high - response; 224cf200d32Sopenharmony_ci } // if 225cf200d32Sopenharmony_ci 226cf200d32Sopenharmony_ci if (badInput) 227cf200d32Sopenharmony_ci response = UINT64_C(0); 228cf200d32Sopenharmony_ci 229cf200d32Sopenharmony_ci return response; 230cf200d32Sopenharmony_ci} // IeeeToInt() 231cf200d32Sopenharmony_ci 232cf200d32Sopenharmony_ci// Takes a size and converts this to a size in IEEE-1541-2002 units (KiB, MiB, 233cf200d32Sopenharmony_ci// GiB, TiB, PiB, or EiB), returned in C++ string form. The size is either in 234cf200d32Sopenharmony_ci// units of the sector size or, if that parameter is omitted, in bytes. 235cf200d32Sopenharmony_ci// (sectorSize defaults to 1). Note that this function uses peculiar 236cf200d32Sopenharmony_ci// manual computation of decimal value rather than simply setting 237cf200d32Sopenharmony_ci// theValue.precision() because this isn't possible using the available 238cf200d32Sopenharmony_ci// EFI library. 239cf200d32Sopenharmony_cistring BytesToIeee(uint64_t size, uint32_t sectorSize) { 240cf200d32Sopenharmony_ci uint64_t sizeInIeee; 241cf200d32Sopenharmony_ci uint64_t previousIeee; 242cf200d32Sopenharmony_ci float decimalIeee; 243cf200d32Sopenharmony_ci uint64_t index = 0; 244cf200d32Sopenharmony_ci string units, prefixes = " KMGTPEZ"; 245cf200d32Sopenharmony_ci ostringstream theValue; 246cf200d32Sopenharmony_ci 247cf200d32Sopenharmony_ci sizeInIeee = previousIeee = size * (uint64_t) sectorSize; 248cf200d32Sopenharmony_ci while ((sizeInIeee > 1024) && (index < (prefixes.length() - 1))) { 249cf200d32Sopenharmony_ci index++; 250cf200d32Sopenharmony_ci previousIeee = sizeInIeee; 251cf200d32Sopenharmony_ci sizeInIeee /= 1024; 252cf200d32Sopenharmony_ci } // while 253cf200d32Sopenharmony_ci if (prefixes[index] == ' ') { 254cf200d32Sopenharmony_ci theValue << sizeInIeee << " bytes"; 255cf200d32Sopenharmony_ci } else { 256cf200d32Sopenharmony_ci units = " iB"; 257cf200d32Sopenharmony_ci units[1] = prefixes[index]; 258cf200d32Sopenharmony_ci decimalIeee = ((float) previousIeee - 259cf200d32Sopenharmony_ci ((float) sizeInIeee * 1024.0) + 51.2) / 102.4; 260cf200d32Sopenharmony_ci if (decimalIeee >= 10.0) { 261cf200d32Sopenharmony_ci decimalIeee = 0.0; 262cf200d32Sopenharmony_ci sizeInIeee++; 263cf200d32Sopenharmony_ci } 264cf200d32Sopenharmony_ci theValue << sizeInIeee << "." << (uint32_t) decimalIeee << units; 265cf200d32Sopenharmony_ci } // if/else 266cf200d32Sopenharmony_ci return theValue.str(); 267cf200d32Sopenharmony_ci} // BytesToIeee() 268cf200d32Sopenharmony_ci 269cf200d32Sopenharmony_ci// Converts two consecutive characters in the input string into a 270cf200d32Sopenharmony_ci// number, interpreting the string as a hexadecimal number, starting 271cf200d32Sopenharmony_ci// at the specified position. 272cf200d32Sopenharmony_ciunsigned char StrToHex(const string & input, unsigned int position) { 273cf200d32Sopenharmony_ci unsigned char retval = 0x00; 274cf200d32Sopenharmony_ci unsigned int temp; 275cf200d32Sopenharmony_ci 276cf200d32Sopenharmony_ci if (input.length() > position) { 277cf200d32Sopenharmony_ci sscanf(input.substr(position, 2).c_str(), "%x", &temp); 278cf200d32Sopenharmony_ci retval = (unsigned char) temp; 279cf200d32Sopenharmony_ci } // if 280cf200d32Sopenharmony_ci return retval; 281cf200d32Sopenharmony_ci} // StrToHex() 282cf200d32Sopenharmony_ci 283cf200d32Sopenharmony_ci// Returns 1 if input can be interpreted as a hexadecimal number -- 284cf200d32Sopenharmony_ci// all characters must be spaces, digits, or letters A-F (upper- or 285cf200d32Sopenharmony_ci// lower-case), with at least one valid hexadecimal digit; with the 286cf200d32Sopenharmony_ci// exception of the first two characters, which may be "0x"; otherwise 287cf200d32Sopenharmony_ci// returns 0. 288cf200d32Sopenharmony_ciint IsHex(string input) { 289cf200d32Sopenharmony_ci int isHex = 1, foundHex = 0, i; 290cf200d32Sopenharmony_ci 291cf200d32Sopenharmony_ci if (input.substr(0, 2) == "0x") 292cf200d32Sopenharmony_ci input.erase(0, 2); 293cf200d32Sopenharmony_ci for (i = 0; i < (int) input.length(); i++) { 294cf200d32Sopenharmony_ci if ((input[i] < '0') || (input[i] > '9')) { 295cf200d32Sopenharmony_ci if ((input[i] < 'A') || (input[i] > 'F')) { 296cf200d32Sopenharmony_ci if ((input[i] < 'a') || (input[i] > 'f')) { 297cf200d32Sopenharmony_ci if ((input[i] != ' ') && (input[i] != '\n')) { 298cf200d32Sopenharmony_ci isHex = 0; 299cf200d32Sopenharmony_ci } 300cf200d32Sopenharmony_ci } else foundHex = 1; 301cf200d32Sopenharmony_ci } else foundHex = 1; 302cf200d32Sopenharmony_ci } else foundHex = 1; 303cf200d32Sopenharmony_ci } // for 304cf200d32Sopenharmony_ci if (!foundHex) 305cf200d32Sopenharmony_ci isHex = 0; 306cf200d32Sopenharmony_ci return isHex; 307cf200d32Sopenharmony_ci} // IsHex() 308cf200d32Sopenharmony_ci 309cf200d32Sopenharmony_ci// Return 1 if the CPU architecture is little endian, 0 if it's big endian.... 310cf200d32Sopenharmony_ciint IsLittleEndian(void) { 311cf200d32Sopenharmony_ci int littleE = 1; // assume little-endian (Intel-style) 312cf200d32Sopenharmony_ci union { 313cf200d32Sopenharmony_ci uint32_t num; 314cf200d32Sopenharmony_ci unsigned char uc[sizeof(uint32_t)]; 315cf200d32Sopenharmony_ci } endian; 316cf200d32Sopenharmony_ci 317cf200d32Sopenharmony_ci endian.num = 1; 318cf200d32Sopenharmony_ci if (endian.uc[0] != (unsigned char) 1) { 319cf200d32Sopenharmony_ci littleE = 0; 320cf200d32Sopenharmony_ci } // if 321cf200d32Sopenharmony_ci return (littleE); 322cf200d32Sopenharmony_ci} // IsLittleEndian() 323cf200d32Sopenharmony_ci 324cf200d32Sopenharmony_ci// Reverse the byte order of theValue; numBytes is number of bytes 325cf200d32Sopenharmony_civoid ReverseBytes(void* theValue, int numBytes) { 326cf200d32Sopenharmony_ci char* tempValue = NULL; 327cf200d32Sopenharmony_ci int i; 328cf200d32Sopenharmony_ci 329cf200d32Sopenharmony_ci tempValue = new char [numBytes]; 330cf200d32Sopenharmony_ci if (tempValue != NULL) { 331cf200d32Sopenharmony_ci memcpy(tempValue, theValue, numBytes); 332cf200d32Sopenharmony_ci for (i = 0; i < numBytes; i++) 333cf200d32Sopenharmony_ci ((char*) theValue)[i] = tempValue[numBytes - i - 1]; 334cf200d32Sopenharmony_ci delete[] tempValue; 335cf200d32Sopenharmony_ci } else { 336cf200d32Sopenharmony_ci cerr << "Could not allocate memory in ReverseBytes()! Terminating\n"; 337cf200d32Sopenharmony_ci exit(1); 338cf200d32Sopenharmony_ci } // if/else 339cf200d32Sopenharmony_ci} // ReverseBytes() 340cf200d32Sopenharmony_ci 341cf200d32Sopenharmony_ci// On Windows, display a warning and ask whether to continue. If the user elects 342cf200d32Sopenharmony_ci// not to continue, exit immediately. 343cf200d32Sopenharmony_civoid WinWarning(void) { 344cf200d32Sopenharmony_ci #ifdef _WIN32 345cf200d32Sopenharmony_ci cout << "\a************************************************************************\n" 346cf200d32Sopenharmony_ci << "Most versions of Windows cannot boot from a GPT disk except on a UEFI-based\n" 347cf200d32Sopenharmony_ci << "computer, and most varieties prior to Vista cannot read GPT disks. Therefore,\n" 348cf200d32Sopenharmony_ci << "you should exit now unless you understand the implications of converting MBR\n" 349cf200d32Sopenharmony_ci << "to GPT or creating a new GPT disk layout!\n" 350cf200d32Sopenharmony_ci << "************************************************************************\n\n"; 351cf200d32Sopenharmony_ci cout << "Are you SURE you want to continue? "; 352cf200d32Sopenharmony_ci if (GetYN() != 'Y') 353cf200d32Sopenharmony_ci exit(0); 354cf200d32Sopenharmony_ci #endif 355cf200d32Sopenharmony_ci} // WinWarning() 356cf200d32Sopenharmony_ci 357cf200d32Sopenharmony_ci// Returns the input string in lower case 358cf200d32Sopenharmony_cistring ToLower(const string& input) { 359cf200d32Sopenharmony_ci string lower = input; // allocate correct size through copy 360cf200d32Sopenharmony_ci 361cf200d32Sopenharmony_ci transform(input.begin(), input.end(), lower.begin(), ::tolower); 362cf200d32Sopenharmony_ci return lower; 363cf200d32Sopenharmony_ci} // ToLower() 364