disks.c revision 26717
1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 * 7 * $Id: disks.c,v 1.87 1997/06/12 08:46:50 jkh Exp $ 8 * 9 * Copyright (c) 1995 10 * Jordan Hubbard. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * verbatim and that no modifications are made prior to this 18 * point in the file. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 37#include "sysinstall.h" 38#include <ctype.h> 39#include <sys/disklabel.h> 40 41/* Where we start displaying chunk information on the screen */ 42#define CHUNK_START_ROW 5 43 44/* Where we keep track of MBR chunks */ 45static struct chunk *chunk_info[16]; 46static int current_chunk; 47 48static void diskPartitionNonInteractive(Device *dev, Disk *d); 49 50static void 51record_chunks(Disk *d) 52{ 53 struct chunk *c1 = NULL; 54 int i = 0; 55 int last_free = 0; 56 57 if (!d->chunks) 58 msgFatal("No chunk list found for %s!", d->name); 59 60 for (c1 = d->chunks->part; c1; c1 = c1->next) { 61 if (c1->type == unused && c1->size > last_free) { 62 last_free = c1->size; 63 current_chunk = i; 64 } 65 chunk_info[i++] = c1; 66 } 67 chunk_info[i] = NULL; 68 if (current_chunk >= i) 69 current_chunk = i - 1; 70} 71 72static int Total; 73 74static void 75print_chunks(Disk *d) 76{ 77 int row; 78 int i; 79 80 for (i = Total = 0; chunk_info[i]; i++) 81 Total += chunk_info[i]->size; 82 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { 83 dialog_clear_norefresh(); 84 msgConfirm("WARNING: A geometry of %d/%d/%d for %s is incorrect. Using\n" 85 "a more likely geometry. If this geometry is incorrect or you\n" 86 "are unsure as to whether or not it's correct, please consult\n" 87 "the Hardware Guide in the Documentation submenu or use the\n" 88 "(G)eometry command to change it now.\n\n" 89 "Remember: you need to enter whatever your BIOS thinks the\n" 90 "geometry is! For IDE, it's what you were told in the BIOS\n" 91 "setup. For SCSI, it's the translation mode your controller is\n" 92 "using. Do NOT use a ``physical geometry''.", 93 d->bios_cyl, d->bios_hd, d->bios_sect, d->name); 94 Sanitize_Bios_Geom(d); 95 } 96 attrset(A_NORMAL); 97 mvaddstr(0, 0, "Disk name:\t"); 98 clrtobot(); 99 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 100 attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 101 mvprintw(1, 0, 102 "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %lu sectors", 103 d->bios_cyl, d->bios_hd, d->bios_sect, 104 d->bios_cyl * d->bios_hd * d->bios_sect); 105 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", 106 "Offset", "Size", "End", "Name", "PType", "Desc", 107 "Subtype", "Flags"); 108 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 109 if (i == current_chunk) 110 attrset(ATTR_SELECTED); 111 mvprintw(row, 2, "%10ld %10lu %10lu %8s %8d %8s %8d\t%-6s", 112 chunk_info[i]->offset, chunk_info[i]->size, 113 chunk_info[i]->end, chunk_info[i]->name, 114 chunk_info[i]->type, 115 slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), 116 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 117 if (i == current_chunk) 118 attrset(A_NORMAL); 119 } 120} 121 122static void 123print_command_summary() 124{ 125 mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 126 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Slice"); 127 mvprintw(17, 0, "D = Delete Slice G = Set Drive Geometry S = Set Bootable"); 128 mvprintw(18, 0, "U = Undo All Changes Q = Finish"); 129 if (!RunningAsInit) 130 mvprintw(18, 48, "W = Write Changes"); 131 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); 132 move(0, 0); 133} 134 135static u_char * 136getBootMgr(char *dname) 137{ 138 extern u_char mbr[], bteasy17[]; 139 char str[80]; 140 char *cp; 141 int i = 0; 142 143 cp = variable_get(VAR_BOOTMGR); 144 if (!cp) { 145 /* Figure out what kind of MBR the user wants */ 146 sprintf(str, "Install Boot Manager for drive %s?", dname); 147 MenuMBRType.title = str; 148 i = dmenuOpenSimple(&MenuMBRType, FALSE); 149 } 150 else { 151 if (!strncmp(cp, "boot", 4)) 152 BootMgr = 0; 153 else if (!strcmp(cp, "standard")) 154 BootMgr = 1; 155 else 156 BootMgr = 2; 157 } 158 if (cp || i) { 159 switch (BootMgr) { 160 case 0: 161 return bteasy17; 162 163 case 1: 164 return mbr; 165 166 case 2: 167 default: 168 break; 169 } 170 } 171 return NULL; 172} 173 174void 175diskPartition(Device *dev, Disk *d) 176{ 177 char *cp, *p; 178 int rv, key = 0; 179 Boolean chunking; 180 char *msg = NULL; 181 u_char *mbrContents; 182 WINDOW *w = savescr(); 183 184 chunking = TRUE; 185 keypad(stdscr, TRUE); 186 187 /* Flush both the dialog and curses library views of the screen 188 since we don't always know who called us */ 189 dialog_clear_norefresh(), clear(); 190 current_chunk = 0; 191 192 /* Set up the chunk array */ 193 record_chunks(d); 194 195 while (chunking) { 196 char *val, geometry[80]; 197 198 /* Now print our overall state */ 199 if (d) 200 print_chunks(d); 201 print_command_summary(); 202 if (msg) { 203 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 204 beep(); 205 msg = NULL; 206 } 207 else { 208 move(23, 0); 209 clrtoeol(); 210 } 211 212 /* Get command character */ 213 key = getch(); 214 switch (toupper(key)) { 215 case '\014': /* ^L (redraw) */ 216 clear(); 217 msg = NULL; 218 break; 219 220 case '\020': /* ^P */ 221 case KEY_UP: 222 case '-': 223 if (current_chunk != 0) 224 --current_chunk; 225 break; 226 227 case '\016': /* ^N */ 228 case KEY_DOWN: 229 case '+': 230 case '\r': 231 case '\n': 232 if (chunk_info[current_chunk + 1]) 233 ++current_chunk; 234 break; 235 236 case KEY_HOME: 237 current_chunk = 0; 238 break; 239 240 case KEY_END: 241 while (chunk_info[current_chunk + 1]) 242 ++current_chunk; 243 break; 244 245 case KEY_F(1): 246 case '?': 247 systemDisplayHelp("slice"); 248 clear(); 249 break; 250 251 case 'A': 252 cp = variable_get(VAR_DEDICATE_DISK); 253 if (cp && !strcasecmp(cp, "always")) 254 rv = 1; 255 else { 256 rv = msgYesNo("Do you want to do this with a true partition entry\n" 257 "so as to remain cooperative with any future possible\n" 258 "operating systems on the drive(s)?"); 259 if (rv != 0 && (!cp || strcasecmp(cp, "nowarn")) && !variable_get(VAR_NO_WARN)) { 260 rv = !msgYesNo("This is dangerous in that it will make the drive totally\n" 261 "uncooperative with other potential operating systems on the\n" 262 "same disk. It will lead instead to a totally dedicated disk,\n" 263 "starting at the very first sector, bypassing all BIOS geometry\n" 264 "considerations. This precludes the existance of any boot\n" 265 "manager or other stuff in sector 0, since the BSD bootstrap\n" 266 "will live there.\n" 267 "You will run into serious trouble with ST-506 and ESDI drives\n" 268 "and possibly some IDE drives (e.g. drives running under the\n" 269 "control of sort of disk manager). SCSI drives are considerably\n" 270 "less at risk.\n\n" 271 "If, on the other hand, your goal is a dedicated FreeBSD machine\n" 272 "and nothing else, this option is for you.\n\n" 273 "Do you insist on dedicating the entire disk this way?"); 274 } 275 if (rv == -1) 276 rv = 0; 277 } 278 All_FreeBSD(d, rv); 279 variable_set2(DISK_PARTITIONED, "yes"); 280 record_chunks(d); 281 clear(); 282 break; 283 284 case 'B': 285 if (chunk_info[current_chunk]->type != freebsd) 286 msg = "Can only scan for bad blocks in FreeBSD slice."; 287 else if (strncmp(d->name, "sd", 2) || 288 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n" 289 "Are you sure you want to do this on a SCSI disk?")) { 290 if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 291 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 292 else 293 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 294 } 295 clear(); 296 break; 297 298 case 'C': 299 if (chunk_info[current_chunk]->type != unused) 300 msg = "Slice in use, delete it first or move to an unused one."; 301 else { 302 char *val, tmp[20], *cp; 303 int size, subtype; 304 chunk_e partitiontype; 305 306 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); 307 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 308 "or append a trailing `M' for megabytes (e.g. 20M)."); 309 if (val && (size = strtol(val, &cp, 0)) > 0) { 310 if (*cp && toupper(*cp) == 'M') 311 size *= ONE_MEG; 312 strcpy(tmp, "165"); 313 val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 314 "Pressing Enter will choose the default, a native FreeBSD\n" 315 "slice (type 165). You can choose other types, 6 for a\n" 316 "DOS partition or 131 for a Linux partition, for example.\n\n" 317 "Note: If you choose a non-FreeBSD partition type, it will not\n" 318 "be formatted or otherwise prepared, it will simply reserve space\n" 319 "for you to use another tool, such as DOS FORMAT, to later format\n" 320 "and use the partition."); 321 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 322 if (subtype==165) 323 partitiontype=freebsd; 324 else if (subtype==6) 325 partitiontype=fat; 326 else 327 partitiontype=unknown; 328 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 329 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 330 variable_set2(DISK_PARTITIONED, "yes"); 331 record_chunks(d); 332 } 333 } 334 clear(); 335 } 336 break; 337 338 case KEY_DC: 339 case 'D': 340 if (chunk_info[current_chunk]->type == unused) 341 msg = "Slice is already unused!"; 342 else { 343 Delete_Chunk(d, chunk_info[current_chunk]); 344 variable_set2(DISK_PARTITIONED, "yes"); 345 record_chunks(d); 346 } 347 break; 348 349 case 'G': 350 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 351 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 352 "Don't forget to use the two slash (/) separator characters!\n" 353 "It's not possible to parse the field without them."); 354 if (val) { 355 long nc, nh, ns; 356 nc = strtol(val, &val, 0); 357 nh = strtol(val + 1, &val, 0); 358 ns = strtol(val + 1, 0, 0); 359 Set_Bios_Geom(d, nc, nh, ns); 360 } 361 clear(); 362 break; 363 364 case 'S': 365 /* Set Bootable */ 366 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 367 break; 368 369 case 'U': 370 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 371 msgConfirm("You've already written this information out - you\n" 372 "can't undo it."); 373 } 374 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 375 char cp[BUFSIZ]; 376 377 sstrncpy(cp, d->name, sizeof cp); 378 Free_Disk(dev->private); 379 d = Open_Disk(cp); 380 if (!d) 381 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 382 dev->private = d; 383 variable_unset(DISK_PARTITIONED); 384 variable_unset(DISK_LABELLED); 385 if (d) 386 record_chunks(d); 387 } 388 clear(); 389 break; 390 391 case 'W': 392 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 393 msgConfirm("You've already written this information out - if\n" 394 "you wish to overwrite it, you'll have to restart."); 395 } 396 else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 397 "installation. If you are installing FreeBSD for the first time\n" 398 "then you should simply type Q when you're finished here and your\n" 399 "changes will be committed in one batch automatically at the end of\n" 400 "these questions.\n\n" 401 "Are you absolutely sure you want to do this now?")) { 402 variable_set2(DISK_PARTITIONED, "yes"); 403 404 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 405 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 406 * booteasy or a "standard" MBR -- both would be fatal in this case. 407 */ 408 if (!(d->chunks->part->flags & CHUNK_FORCE_ALL) && (mbrContents = getBootMgr(d->name)) != NULL) 409 Set_Boot_Mgr(d, mbrContents); 410 411 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 412 msgConfirm("Disk partition write returned an error status!"); 413 else 414 msgConfirm("Wrote FDISK partition information out successfully."); 415 } 416 clear(); 417 break; 418 419 case '|': 420 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 421 "No seat belts whatsoever are provided!")) { 422 clear(); 423 refresh(); 424 slice_wizard(d); 425 variable_set2(DISK_PARTITIONED, "yes"); 426 record_chunks(d); 427 } 428 else 429 msg = "Wise choice!"; 430 clear(); 431 break; 432 433 case '\033': /* ESC */ 434 case 'Q': 435 chunking = FALSE; 436 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 437 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 438 * booteasy or a "standard" MBR -- both would be fatal in this case. 439 */ 440 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 441 && (mbrContents = getBootMgr(d->name)) != NULL) 442 Set_Boot_Mgr(d, mbrContents); 443 break; 444 445 default: 446 beep(); 447 msg = "Type F1 or ? for help"; 448 break; 449 } 450 } 451 p = CheckRules(d); 452 if (p) { 453 char buf[FILENAME_MAX]; 454 455 dialog_clear_norefresh(); 456 use_helpline("Press F1 to read more about disk slices."); 457 use_helpfile(systemHelpFile("partition", buf)); 458 if (!variable_get(VAR_NO_WARN)) 459 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 460 free(p); 461 } 462 restorescr(w); 463} 464 465static int 466partitionHook(dialogMenuItem *selected) 467{ 468 Device **devs = NULL; 469 470 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 471 if (!devs) { 472 msgConfirm("Unable to find disk %s!", selected->prompt); 473 return DITEM_FAILURE; 474 } 475 /* Toggle enabled status? */ 476 if (!devs[0]->enabled) { 477 devs[0]->enabled = TRUE; 478 diskPartition(devs[0], (Disk *)devs[0]->private); 479 } 480 else 481 devs[0]->enabled = FALSE; 482 return DITEM_SUCCESS | DITEM_REDRAW; 483} 484 485static int 486partitionCheck(dialogMenuItem *selected) 487{ 488 Device **devs = NULL; 489 490 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 491 if (!devs || devs[0]->enabled == FALSE) 492 return FALSE; 493 return TRUE; 494} 495 496int 497diskPartitionEditor(dialogMenuItem *self) 498{ 499 DMenu *menu; 500 Device **devs; 501 int i, cnt; 502 char *cp; 503 504 cp = variable_get(VAR_DISK); 505 devs = deviceFind(cp, DEVICE_TYPE_DISK); 506 cnt = deviceCount(devs); 507 if (!cnt) { 508 msgConfirm("No disks found! Please verify that your disk controller is being\n" 509 "properly probed at boot time. See the Hardware Guide on the\n" 510 "Documentation menu for clues on diagnosing this type of problem."); 511 i = DITEM_FAILURE; 512 } 513 else if (cnt == 1) { 514 devs[0]->enabled = TRUE; 515 if (variable_get(VAR_NONINTERACTIVE)) 516 diskPartitionNonInteractive(devs[0], (Disk *)devs[0]->private); 517 else 518 diskPartition(devs[0], (Disk *)devs[0]->private); 519 i = DITEM_SUCCESS; 520 } 521 else { 522 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 523 if (!menu) { 524 msgConfirm("No devices suitable for installation found!\n\n" 525 "Please verify that your disk controller (and attached drives)\n" 526 "were detected properly. This can be done by pressing the\n" 527 "[Scroll Lock] key and using the Arrow keys to move back to\n" 528 "the boot messages. Press [Scroll Lock] again to return."); 529 i = DITEM_FAILURE; 530 } 531 else { 532 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 533 free(menu); 534 } 535 i = i | DITEM_RESTORE; 536 } 537 return i; 538} 539 540int 541diskPartitionWrite(dialogMenuItem *self) 542{ 543 Device **devs; 544 char *cp; 545 int i; 546 547 if ((cp = variable_get(DISK_PARTITIONED)) && strcmp(cp, "yes")) 548 return DITEM_SUCCESS; 549 else if (!cp) { 550 msgConfirm("You must partition the disk(s) before this option can be used."); 551 return DITEM_FAILURE; 552 } 553 554 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 555 if (!devs) { 556 msgConfirm("Unable to find any disks to write to??"); 557 return DITEM_FAILURE; 558 } 559 if (isDebug()) 560 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 561 562 for (i = 0; devs[i]; i++) { 563 Chunk *c1; 564 Disk *d = (Disk *)devs[i]->private; 565 566 if (!devs[i]->enabled) 567 continue; 568 569 Set_Boot_Blocks(d, boot1, boot2); 570 msgNotify("Writing partition information to drive %s", d->name); 571 if (!Fake && Write_Disk(d)) { 572 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 573 return DITEM_FAILURE; 574 } 575 /* Now scan for bad blocks, if necessary */ 576 for (c1 = d->chunks->part; c1; c1 = c1->next) { 577 if (c1->flags & CHUNK_BAD144) { 578 int ret; 579 580 msgNotify("Running bad block scan on slice %s", c1->name); 581 if (!Fake) { 582 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 583 if (ret) 584 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 585 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 586 if (ret) 587 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 588 } 589 } 590 } 591 } 592 /* Now it's not "yes", but "written" */ 593 variable_set2(DISK_PARTITIONED, "written"); 594 return DITEM_SUCCESS; 595} 596 597/* Partition a disk based wholly on which variables are set */ 598static void 599diskPartitionNonInteractive(Device *dev, Disk *d) 600{ 601 char *cp; 602 int i, sz, all_disk = 0; 603 u_char *mbrContents; 604 605 record_chunks(d); 606 cp = variable_get(VAR_GEOMETRY); 607 if (cp) { 608 msgDebug("Setting geometry from script to: %s\n", cp); 609 d->bios_cyl = strtol(cp, &cp, 0); 610 d->bios_hd = strtol(cp + 1, &cp, 0); 611 d->bios_sect = strtol(cp + 1, 0, 0); 612 } 613 614 cp = variable_get(VAR_PARTITION); 615 if (cp) { 616 if (!strcmp(cp, "free")) { 617 /* Do free disk space case */ 618 for (i = 0; chunk_info[i]; i++) { 619 /* If a chunk is at least 10MB in size, use it. */ 620 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 621 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 622 (chunk_info[i]->flags & CHUNK_ALIGN)); 623 variable_set2(DISK_PARTITIONED, "yes"); 624 break; 625 } 626 } 627 if (!chunk_info[i]) { 628 dialog_clear(); 629 msgConfirm("Unable to find any free space on this disk!"); 630 return; 631 } 632 } 633 else if (!strcmp(cp, "all")) { 634 /* Do all disk space case */ 635 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 636 637 All_FreeBSD(d, FALSE); 638 } 639 else if (!strcmp(cp, "exclusive")) { 640 /* Do really-all-the-disk-space case */ 641 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 642 643 All_FreeBSD(d, all_disk = TRUE); 644 } 645 else if ((sz = strtol(cp, &cp, 0))) { 646 /* Look for sz bytes free */ 647 if (*cp && toupper(*cp) == 'M') 648 sz *= ONE_MEG; 649 for (i = 0; chunk_info[i]; i++) { 650 /* If a chunk is at least sz MB, use it. */ 651 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 652 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 653 variable_set2(DISK_PARTITIONED, "yes"); 654 break; 655 } 656 } 657 if (!chunk_info[i]) { 658 dialog_clear(); 659 msgConfirm("Unable to find %d free blocks on this disk!", sz); 660 return; 661 } 662 } 663 else if (!strcmp(cp, "existing")) { 664 /* Do existing FreeBSD case */ 665 for (i = 0; chunk_info[i]; i++) { 666 if (chunk_info[i]->type == freebsd) 667 break; 668 } 669 if (!chunk_info[i]) { 670 dialog_clear(); 671 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 672 return; 673 } 674 } 675 else { 676 dialog_clear(); 677 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 678 return; 679 } 680 if (!all_disk) { 681 mbrContents = getBootMgr(d->name); 682 Set_Boot_Mgr(d, mbrContents); 683 } 684 variable_set2(DISK_PARTITIONED, "yes"); 685 } 686} 687