blob: 612c52603619cfa8382d805e866f1004a27a2910 [file] [log] [blame]
srs56941e093722010-01-05 00:14:19 -05001// sgdisk.cc
srs569473ba4792010-01-12 18:18:17 -05002// Command-line-based version of gdisk. This program is named after sfdisk,
3// and it can serve a similar role (easily scripted, etc.), but it's used
4// strictly via command-line arguments, and it doesn't bear much resemblance
5// to sfdisk in actual use.
srs56941e093722010-01-05 00:14:19 -05006//
srs569473ba4792010-01-12 18:18:17 -05007// by Rod Smith, project began February 2009; sgdisk begun January 2010.
srs56941e093722010-01-05 00:14:19 -05008
9/* This program is copyright (c) 2009, 2010 by Roderick W. Smith. It is distributed
10 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
11
srs56941e093722010-01-05 00:14:19 -050012#include <stdio.h>
srs569473ba4792010-01-12 18:18:17 -050013#include <string>
14#include <popt.h>
15#include <errno.h>
srs5694fed16d02010-01-27 23:03:40 -050016#include <iostream>
srs569455d92612010-03-07 22:16:07 -050017#include <sstream>
srs56941e093722010-01-05 00:14:19 -050018#include "mbr.h"
19#include "gpt.h"
20#include "support.h"
srs569473ba4792010-01-12 18:18:17 -050021#include "parttypes.h"
srs56949ddc14b2010-08-22 22:44:42 -040022#include "attributes.h"
srs569473ba4792010-01-12 18:18:17 -050023
24using namespace std;
srs56941e093722010-01-05 00:14:19 -050025
26#define MAX_OPTIONS 50
27
srs569408bb0da2010-02-19 17:19:55 -050028int BuildMBR(GPTData* theGPT, char* argument, int isHybrid);
29int CountColons(char* argument);
srs56941e093722010-01-05 00:14:19 -050030
srs569473ba4792010-01-12 18:18:17 -050031int main(int argc, char *argv[]) {
srs56941e093722010-01-05 00:14:19 -050032 GPTData theGPT;
srs5694e321d442010-01-29 17:44:04 -050033 int opt, numOptions = 0, saveData = 0, neverSaveData = 0;
srs56949ba54212010-05-18 23:24:02 -040034 int partNum = 0, deletePartNum = 0, infoPartNum = 0, bsdPartNum = 0, largestPartNum = 0;
35 int saveNonGPT = 1;
36 uint32_t gptPartNum = 0;
srs5694a8582cf2010-03-19 14:21:59 -040037 int alignment = DEFAULT_ALIGNMENT, retval = 0, pretend = 0;
srs5694e321d442010-01-29 17:44:04 -050038 unsigned int hexCode;
srs569473ba4792010-01-12 18:18:17 -050039 uint32_t tableSize = 128;
40 uint64_t startSector, endSector;
srs56949ddc14b2010-08-22 22:44:42 -040041 char *attributeOperation = NULL;
srs5694e321d442010-01-29 17:44:04 -050042 char *device = NULL;
srs569408bb0da2010-02-19 17:19:55 -050043 char *newPartInfo = NULL, *typeCode = NULL, *partName = NULL;
44 char *backupFile = NULL, *twoParts = NULL, *hybrids = NULL, *mbrParts;
srs5694f9312b02010-07-06 15:39:51 -040045 char *partGUID = NULL, *diskGUID = NULL, *outDevice = NULL;
srs5694327129e2010-09-22 01:07:31 -040046 string cmd, typeGUID;
srs56946699b012010-02-04 00:55:30 -050047 PartType typeHelper;
srs56941e093722010-01-05 00:14:19 -050048
srs569473ba4792010-01-12 18:18:17 -050049 poptContext poptCon;
50 struct poptOption theOptions[] =
51 {
srs56949ddc14b2010-08-22 22:44:42 -040052 {"attributes", 'A', POPT_ARG_STRING, &attributeOperation, 'A', "operate on partition attributes", "list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]"},
srs569473ba4792010-01-12 18:18:17 -050053 {"set-alignment", 'a', POPT_ARG_INT, &alignment, 'a', "set sector alignment", "value"},
54 {"backup", 'b', POPT_ARG_STRING, &backupFile, 'b', "backup GPT to file", "file"},
55 {"change-name", 'c', POPT_ARG_STRING, &partName, 'c', "change partition's name", "partnum:name"},
srs56949ba54212010-05-18 23:24:02 -040056 {"recompute-chs", 'C', POPT_ARG_NONE, NULL, 'C', "recompute CHS values in protective/hybrid MBR", ""},
srs569473ba4792010-01-12 18:18:17 -050057 {"delete", 'd', POPT_ARG_INT, &deletePartNum, 'd', "delete a partition", "partnum"},
srs569455d92612010-03-07 22:16:07 -050058 {"display-alignment", 'D', POPT_ARG_NONE, NULL, 'D', "show number of sectors per allocation block", ""},
srs569473ba4792010-01-12 18:18:17 -050059 {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second header to end of disk", ""},
60 {"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""},
61 {"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""},
62 {"mbrtogpt", 'g', POPT_ARG_NONE, NULL, 'g', "convert MBR to GPT", ""},
srs56949ba54212010-05-18 23:24:02 -040063 {"randomize-guids", 'G', POPT_ARG_NONE, NULL, 'G', "randomize disk and partition GUIDs", ""},
srs569408bb0da2010-02-19 17:19:55 -050064 {"hybrid", 'h', POPT_ARG_STRING, &hybrids, 'h', "create hybrid MBR", "partnum[:partnum...]"},
srs569473ba4792010-01-12 18:18:17 -050065 {"info", 'i', POPT_ARG_INT, &infoPartNum, 'i', "show detailed information on partition", "partnum"},
66 {"load-backup", 'l', POPT_ARG_STRING, &backupFile, 'l', "load GPT backup from file", "file"},
67 {"list-types", 'L', POPT_ARG_NONE, NULL, 'L', "list known partition types", ""},
srs569408bb0da2010-02-19 17:19:55 -050068 {"gpttombr", 'm', POPT_ARG_STRING, &mbrParts, 'm', "convert GPT to MBR", "partnum[:partnum...]"},
srs569473ba4792010-01-12 18:18:17 -050069 {"new", 'n', POPT_ARG_STRING, &newPartInfo, 'n', "create new partition", "partnum:start:end"},
srs56949ba54212010-05-18 23:24:02 -040070 {"largest-new", 'N', POPT_ARG_INT, &largestPartNum, 'N', "create largest possible new partition", "partnum"},
srs569473ba4792010-01-12 18:18:17 -050071 {"clear", 'o', POPT_ARG_NONE, NULL, 'o', "clear partition table", ""},
72 {"print", 'p', POPT_ARG_NONE, NULL, 'p', "print partition table", ""},
73 {"pretend", 'P', POPT_ARG_NONE, NULL, 'P', "make changes in memory, but don't write them", ""},
srs569408bb0da2010-02-19 17:19:55 -050074 {"transpose", 'r', POPT_ARG_STRING, &twoParts, 'r', "transpose two partitions", "partnum:partnum"},
srs5694f9312b02010-07-06 15:39:51 -040075 {"replicate", 'R', POPT_ARG_STRING, &outDevice, 'R', "replicate partition table", "device_filename"},
srs569473ba4792010-01-12 18:18:17 -050076 {"sort", 's', POPT_ARG_NONE, NULL, 's', "sort partition table entries", ""},
77 {"resize-table", 'S', POPT_ARG_INT, &tableSize, 'S', "resize partition table", "numparts"},
srs5694327129e2010-09-22 01:07:31 -040078 {"typecode", 't', POPT_ARG_STRING, &typeCode, 't', "change partition type code", "partnum:{hexcode|GUID}"},
srs569473ba4792010-01-12 18:18:17 -050079 {"transform-bsd", 'T', POPT_ARG_INT, &bsdPartNum, 'T', "transform BSD disklabel partition to GPT", "partnum"},
srs56949ba54212010-05-18 23:24:02 -040080 {"partition-guid", 'u', POPT_ARG_STRING, &partGUID, 'u', "set partition GUID", "partnum:guid"},
81 {"disk-guid", 'U', POPT_ARG_STRING, &diskGUID, 'U', "set disk GUID", "guid"},
srs569473ba4792010-01-12 18:18:17 -050082 {"verify", 'v', POPT_ARG_NONE, NULL, 'v', "check partition table integrity", ""},
83 {"version", 'V', POPT_ARG_NONE, NULL, 'V', "display version information", ""},
srs569408bb0da2010-02-19 17:19:55 -050084 {"zap", 'z', POPT_ARG_NONE, NULL, 'z', "zap (destroy) GPT (but not MBR) data structures", ""},
85 {"zap-all", 'Z', POPT_ARG_NONE, NULL, 'Z', "zap (destroy) GPT and MBR data structures", ""},
srs569473ba4792010-01-12 18:18:17 -050086 POPT_AUTOHELP { NULL, 0, 0, NULL, 0 }
87 };
88
89 // Create popt context...
90 poptCon = poptGetContext(NULL, argc, (const char**) argv, theOptions, 0);
91
92 poptSetOtherOptionHelp(poptCon, " [OPTION...] <device>");
93
94 if (argc < 2) {
95 poptPrintUsage(poptCon, stderr, 0);
96 exit(1);
97 }
98
99 // Do one loop through the options to find the device filename and deal
100 // with options that don't require a device filename....
101 while ((opt = poptGetNextOpt(poptCon)) > 0) {
102 switch (opt) {
srs56949ddc14b2010-08-22 22:44:42 -0400103 case 'A':
104 cmd = GetString(attributeOperation, 1);
105 if (cmd == "list")
106 Attributes::ListAttributes();
107 break;
srs569473ba4792010-01-12 18:18:17 -0500108 case 'L':
srs56946699b012010-02-04 00:55:30 -0500109 typeHelper.ShowAllTypes();
srs56941e093722010-01-05 00:14:19 -0500110 break;
srs569473ba4792010-01-12 18:18:17 -0500111 case 'P':
112 pretend = 1;
srs56941e093722010-01-05 00:14:19 -0500113 break;
srs569473ba4792010-01-12 18:18:17 -0500114 case 'V':
srs5694fed16d02010-01-27 23:03:40 -0500115 cout << "GPT fdisk (sgdisk) version " << GPTFDISK_VERSION << "\n\n";
srs56941e093722010-01-05 00:14:19 -0500116 break;
117 default:
srs56941e093722010-01-05 00:14:19 -0500118 break;
119 } // switch
srs569473ba4792010-01-12 18:18:17 -0500120 numOptions++;
121 } // while
srs56941e093722010-01-05 00:14:19 -0500122
srs569473ba4792010-01-12 18:18:17 -0500123 // Assume first non-option argument is the device filename....
124 device = (char*) poptGetArg(poptCon);
125 poptResetContext(poptCon);
srs56941e093722010-01-05 00:14:19 -0500126
srs569473ba4792010-01-12 18:18:17 -0500127 if (device != NULL) {
128 theGPT.JustLooking(); // reset as necessary
129 theGPT.BeQuiet(); // Tell called functions to be less verbose & interactive
srs5694fed16d02010-01-27 23:03:40 -0500130 if (theGPT.LoadPartitions((string) device)) {
srs569473ba4792010-01-12 18:18:17 -0500131 if ((theGPT.WhichWasUsed() == use_mbr) || (theGPT.WhichWasUsed() == use_bsd))
132 saveNonGPT = 0; // flag so we don't overwrite unless directed to do so
133 while ((opt = poptGetNextOpt(poptCon)) > 0) {
134 switch (opt) {
srs56949ddc14b2010-08-22 22:44:42 -0400135 case 'A': {
136 if (cmd != "list") {
137 partNum = (int) GetInt(attributeOperation, 1) - 1;
138 switch (theGPT.ManageAttributes(partNum, GetString(attributeOperation, 2),
139 GetString(attributeOperation, 3))) {
140 case -1:
141 saveData = 0;
142 neverSaveData = 1;
143 break;
144 case 1:
145 theGPT.JustLooking(0);
146 saveData = 1;
147 break;
148 default:
149 break;
150 } // switch
151 } // if
152 break;
153 } // case 'A':
srs569473ba4792010-01-12 18:18:17 -0500154 case 'a':
155 theGPT.SetAlignment(alignment);
156 break;
157 case 'b':
158 theGPT.SaveGPTBackup(backupFile);
159 free(backupFile);
160 break;
161 case 'c':
162 theGPT.JustLooking(0);
163 partNum = (int) GetInt(partName, 1) - 1;
srs5694fed16d02010-01-27 23:03:40 -0500164 if (theGPT.SetName(partNum, GetString(partName, 2))) {
srs569473ba4792010-01-12 18:18:17 -0500165 saveData = 1;
166 } else {
srs56940283dae2010-04-28 16:44:34 -0400167 cerr << "Unable to set partition " << partNum + 1
srs5694fed16d02010-01-27 23:03:40 -0500168 << "'s name to '" << GetString(partName, 2) << "'!\n";
srs569473ba4792010-01-12 18:18:17 -0500169 neverSaveData = 1;
170 } // if/else
171 free(partName);
172 break;
srs5694f9312b02010-07-06 15:39:51 -0400173 case 'C':
174 theGPT.JustLooking(0);
175 theGPT.RecomputeCHS();
176 saveData = 1;
177 break;
srs569473ba4792010-01-12 18:18:17 -0500178 case 'd':
179 theGPT.JustLooking(0);
180 if (theGPT.DeletePartition(deletePartNum - 1) == 0) {
srs5694fed16d02010-01-27 23:03:40 -0500181 cerr << "Error " << errno << " deleting partition!\n";
srs569473ba4792010-01-12 18:18:17 -0500182 neverSaveData = 1;
183 } else saveData = 1;
184 break;
srs569455d92612010-03-07 22:16:07 -0500185 case 'D':
srs56948a4ddfc2010-03-21 19:05:49 -0400186 cout << theGPT.GetAlignment() << "\n";
srs569455d92612010-03-07 22:16:07 -0500187 break;
srs569473ba4792010-01-12 18:18:17 -0500188 case 'e':
189 theGPT.JustLooking(0);
190 theGPT.MoveSecondHeaderToEnd();
191 saveData = 1;
192 break;
193 case 'E':
srs5694cb76c672010-02-11 22:22:22 -0500194 cout << theGPT.FindLastInFree(theGPT.FindFirstInLargest()) << "\n";
srs569473ba4792010-01-12 18:18:17 -0500195 break;
196 case 'f':
srs5694fed16d02010-01-27 23:03:40 -0500197 cout << theGPT.FindFirstInLargest() << "\n";
srs569473ba4792010-01-12 18:18:17 -0500198 break;
199 case 'g':
200 theGPT.JustLooking(0);
201 saveData = 1;
202 saveNonGPT = 1;
203 break;
srs56949ba54212010-05-18 23:24:02 -0400204 case 'G':
205 theGPT.JustLooking(0);
206 saveData = 1;
207 theGPT.RandomizeGUIDs();
208 break;
srs569408bb0da2010-02-19 17:19:55 -0500209 case 'h':
210 theGPT.JustLooking(0);
211 if (BuildMBR(&theGPT, hybrids, 1) == 1)
212 saveData = 1;
213 break;
srs569473ba4792010-01-12 18:18:17 -0500214 case 'i':
215 theGPT.ShowPartDetails(infoPartNum - 1);
216 break;
217 case 'l':
srs5694fed16d02010-01-27 23:03:40 -0500218 if (theGPT.LoadGPTBackup((string) backupFile) == 1)
srs569473ba4792010-01-12 18:18:17 -0500219 saveData = 1;
220 else {
221 saveData = 0;
222 neverSaveData = 1;
srs5694fed16d02010-01-27 23:03:40 -0500223 cerr << "Error loading backup file!\n";
srs569473ba4792010-01-12 18:18:17 -0500224 } // else
225 free(backupFile);
226 break;
227 case 'L':
228 break;
srs569408bb0da2010-02-19 17:19:55 -0500229 case 'm':
230 theGPT.JustLooking(0);
231 if (BuildMBR(&theGPT, mbrParts, 0) == 1) {
232 if (!pretend) {
233 if (theGPT.SaveMBR())
234 theGPT.DestroyGPT();
235 else
236 cerr << "Problem saving MBR!\n";
237 } // if
238 saveNonGPT = 0;
239 saveData = 0;
240 } // if
241 break;
srs569473ba4792010-01-12 18:18:17 -0500242 case 'n':
243 theGPT.JustLooking(0);
244 partNum = (int) GetInt(newPartInfo, 1) - 1;
245 startSector = GetInt(newPartInfo, 2);
246 endSector = GetInt(newPartInfo, 3);
247 if (theGPT.CreatePartition(partNum, startSector, endSector)) {
248 saveData = 1;
249 } else {
srs5694fed16d02010-01-27 23:03:40 -0500250 cerr << "Could not create partition " << partNum << " from "
251 << startSector << " to " << endSector << "\n";
srs569473ba4792010-01-12 18:18:17 -0500252 neverSaveData = 1;
253 } // if/else
254 free(newPartInfo);
255 break;
srs56949ba54212010-05-18 23:24:02 -0400256 case 'N':
257 theGPT.JustLooking(0);
258 startSector = theGPT.FindFirstInLargest();
259 endSector = theGPT.FindLastInFree(startSector);
260 if (theGPT.CreatePartition(largestPartNum - 1, startSector, endSector)) {
261 saveData = 1;
262 } else {
263 cerr << "Could not create partition " << largestPartNum << " from "
264 << startSector << " to " << endSector << "\n";
265 neverSaveData = 1;
266 } // if/else
267 break;
srs569473ba4792010-01-12 18:18:17 -0500268 case 'o':
269 theGPT.JustLooking(0);
270 theGPT.ClearGPTData();
271 saveData = 1;
272 break;
273 case 'p':
274 theGPT.DisplayGPTData();
275 break;
276 case 'P':
277 pretend = 1;
278 break;
srs569408bb0da2010-02-19 17:19:55 -0500279 case 'r':
280 theGPT.JustLooking(0);
281 uint64_t p1, p2;
282 p1 = GetInt(twoParts, 1) - 1;
283 p2 = GetInt(twoParts, 2) - 1;
284 if (theGPT.SwapPartitions((uint32_t) p1, (uint32_t) p2) == 0) {
285 neverSaveData = 1;
286 cerr << "Cannot swap partitions " << p1 + 1 << " and " << p2 + 1 << "\n";
287 } else saveData = 1;
288 break;
srs56949ba54212010-05-18 23:24:02 -0400289 case 'R':
290 theGPT.JustLooking(0);
srs5694f9312b02010-07-06 15:39:51 -0400291 theGPT.SaveGPTData(1, outDevice);
srs56949ba54212010-05-18 23:24:02 -0400292 break;
srs569473ba4792010-01-12 18:18:17 -0500293 case 's':
294 theGPT.JustLooking(0);
295 theGPT.SortGPT();
296 saveData = 1;
297 break;
298 case 'S':
299 theGPT.JustLooking(0);
300 if (theGPT.SetGPTSize(tableSize) == 0)
301 neverSaveData = 1;
302 else
303 saveData = 1;
304 break;
305 case 't':
306 theGPT.JustLooking(0);
307 partNum = (int) GetInt(typeCode, 1) - 1;
srs5694327129e2010-09-22 01:07:31 -0400308 cout << "Got string '" << GetString(typeCode, 2) << "'\n";
309 if (GetString(typeCode, 2).length() < 10) {
310 sscanf(GetString(typeCode, 2).c_str(), "%x", &hexCode);
311 typeHelper = hexCode;
312 } else {
313 typeHelper = GetString(typeCode, 2);
314 } // if/else hexCode or GUID
315 if (theGPT.ChangePartType(partNum, typeHelper)) {
srs569473ba4792010-01-12 18:18:17 -0500316 saveData = 1;
317 } else {
srs5694fed16d02010-01-27 23:03:40 -0500318 cerr << "Could not change partition " << partNum + 1
srs5694327129e2010-09-22 01:07:31 -0400319 << "'s type code to " << GetString(typeCode, 2) << "!\n";
srs569473ba4792010-01-12 18:18:17 -0500320 neverSaveData = 1;
321 } // if/else
322 free(typeCode);
323 break;
324 case 'T':
325 theGPT.JustLooking(0);
srs569408bb0da2010-02-19 17:19:55 -0500326 theGPT.XFormDisklabel(bsdPartNum - 1);
srs569473ba4792010-01-12 18:18:17 -0500327 saveData = 1;
328 break;
srs56949ba54212010-05-18 23:24:02 -0400329 case 'u':
330 theGPT.JustLooking(0);
331 saveData = 1;
332 gptPartNum = (int) GetInt(partGUID, 1) - 1;
333 theGPT.SetPartitionGUID(gptPartNum, GetString(partGUID, 2).c_str());
334 break;
335 case 'U':
336 theGPT.JustLooking(0);
337 saveData = 1;
338 theGPT.SetDiskGUID(diskGUID);
339 break;
srs569473ba4792010-01-12 18:18:17 -0500340 case 'v':
341 theGPT.Verify();
342 break;
343 case 'z':
srs569408bb0da2010-02-19 17:19:55 -0500344 if (!pretend) {
345 theGPT.DestroyGPT();
346 } // if
srs569473ba4792010-01-12 18:18:17 -0500347 saveNonGPT = 0;
srs569408bb0da2010-02-19 17:19:55 -0500348 saveData = 0;
349 break;
350 case 'Z':
351 if (!pretend) {
352 theGPT.DestroyGPT();
353 theGPT.DestroyMBR();
354 } // if
355 saveNonGPT = 0;
356 saveData = 0;
srs569473ba4792010-01-12 18:18:17 -0500357 break;
358 default:
srs5694fed16d02010-01-27 23:03:40 -0500359 cerr << "Unknown option (-" << opt << ")!\n";
srs569473ba4792010-01-12 18:18:17 -0500360 break;
361 } // switch
362 } // while
363 if ((saveData) && (!neverSaveData) && (saveNonGPT) && (!pretend))
364 theGPT.SaveGPTData(1);
365 if (saveData && (!saveNonGPT)) {
srs5694fed16d02010-01-27 23:03:40 -0500366 cout << "Non-GPT disk; not saving changes. Use -g to override.\n";
srs569473ba4792010-01-12 18:18:17 -0500367 retval = 3;
368 } // if
369 if (neverSaveData) {
srs5694fed16d02010-01-27 23:03:40 -0500370 cerr << "Error encountered; not saving changes.\n";
srs569473ba4792010-01-12 18:18:17 -0500371 retval = 4;
372 } // if
373 } else { // if loaded OK
srs56949ddc14b2010-08-22 22:44:42 -0400374 poptResetContext(poptCon);
375 // Do a few types of operations even if there are problems....
376 while ((opt = poptGetNextOpt(poptCon)) > 0) {
377 switch (opt) {
378 case 'v':
srs5694327129e2010-09-22 01:07:31 -0400379 cout << "Verification may miss some problems or report too many!\n";
srs56949ddc14b2010-08-22 22:44:42 -0400380 theGPT.Verify();
381 break;
382 case 'z':
383 if (!pretend) {
384 theGPT.DestroyGPT();
385 } // if
386 saveNonGPT = 0;
387 saveData = 0;
388 break;
389 case 'Z':
390 if (!pretend) {
391 theGPT.DestroyGPT();
392 theGPT.DestroyMBR();
393 } // if
394 saveNonGPT = 0;
395 saveData = 0;
396 break;
397 } // switch
398 } // while
srs569473ba4792010-01-12 18:18:17 -0500399 retval = 2;
400 } // if/else loaded OK
401 } // if (device != NULL)
402 poptFreeContext(poptCon);
srs56941e093722010-01-05 00:14:19 -0500403
srs569473ba4792010-01-12 18:18:17 -0500404 return retval;
405} // main
srs56941e093722010-01-05 00:14:19 -0500406
srs569408bb0da2010-02-19 17:19:55 -0500407// Create a hybrid or regular MBR from GPT data structures
408int BuildMBR(GPTData* theGPT, char* argument, int isHybrid) {
409 int numParts, allOK = 1, i;
srs569455d92612010-03-07 22:16:07 -0500410 PartNotes notes;
411 struct PartInfo *newNote;
srs569408bb0da2010-02-19 17:19:55 -0500412
srs569455d92612010-03-07 22:16:07 -0500413 if ((theGPT != NULL) && (argument != NULL)) {
srs569408bb0da2010-02-19 17:19:55 -0500414 numParts = CountColons(argument) + 1;
415 if (numParts <= (4 - isHybrid)) {
srs569408bb0da2010-02-19 17:19:55 -0500416 for (i = 0; i < numParts; i++) {
srs569455d92612010-03-07 22:16:07 -0500417 newNote = new struct PartInfo;
418 newNote->gptPartNum = GetInt(argument, i + 1) - 1;
419 newNote->active = 0;
420 newNote->hexCode = 0; // code to compute it from default
421 newNote->type = PRIMARY;
422 newNote->firstLBA = theGPT->GetPartFirstLBA(newNote->gptPartNum);
423 newNote->lastLBA = theGPT->GetPartLastLBA(newNote->gptPartNum);
424 notes.AddToEnd(newNote);
srs569408bb0da2010-02-19 17:19:55 -0500425 } // for
srs569455d92612010-03-07 22:16:07 -0500426 if (isHybrid) {
427 newNote = new struct PartInfo;
428 newNote->gptPartNum = MBR_EFI_GPT;
429 newNote->active = 0;
430 newNote->hexCode = 0xEE;
431 newNote->type = PRIMARY;
432 // newNote firstLBA and lastLBA are computed later...
433 notes.AddToStart(newNote);
434 } // if
435 if (theGPT->PartsToMBR(notes) != numParts)
srs569408bb0da2010-02-19 17:19:55 -0500436 allOK = 0;
437 } else allOK = 0;
438 } else allOK = 0;
439 if (!allOK)
440 cerr << "Problem creating MBR!\n";
441 return allOK;
442} // BuildMBR()
443
444// Returns the number of colons in argument string
445int CountColons(char* argument) {
446 int num = 0, i = 0;
447
448 if (argument != NULL) {
449 while (argument[i] != '\0') {
450 if (argument[i++] == ':')
451 num++;
452 } // while
453 } // if
454 return num;
455} // CountColons()