disks.c revision 26574
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.86 1997/06/05 09:47:55 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"))) { 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 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 459 free(p); 460 } 461 restorescr(w); 462} 463 464static int 465partitionHook(dialogMenuItem *selected) 466{ 467 Device **devs = NULL; 468 469 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 470 if (!devs) { 471 msgConfirm("Unable to find disk %s!", selected->prompt); 472 return DITEM_FAILURE; 473 } 474 /* Toggle enabled status? */ 475 if (!devs[0]->enabled) { 476 devs[0]->enabled = TRUE; 477 diskPartition(devs[0], (Disk *)devs[0]->private); 478 } 479 else 480 devs[0]->enabled = FALSE; 481 return DITEM_SUCCESS | DITEM_REDRAW; 482} 483 484static int 485partitionCheck(dialogMenuItem *selected) 486{ 487 Device **devs = NULL; 488 489 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 490 if (!devs || devs[0]->enabled == FALSE) 491 return FALSE; 492 return TRUE; 493} 494 495int 496diskPartitionEditor(dialogMenuItem *self) 497{ 498 DMenu *menu; 499 Device **devs; 500 int i, cnt; 501 char *cp; 502 503 cp = variable_get(VAR_DISK); 504 devs = deviceFind(cp, DEVICE_TYPE_DISK); 505 cnt = deviceCount(devs); 506 if (!cnt) { 507 msgConfirm("No disks found! Please verify that your disk controller is being\n" 508 "properly probed at boot time. See the Hardware Guide on the\n" 509 "Documentation menu for clues on diagnosing this type of problem."); 510 i = DITEM_FAILURE; 511 } 512 else if (cnt == 1) { 513 devs[0]->enabled = TRUE; 514 if (variable_get(VAR_NONINTERACTIVE)) 515 diskPartitionNonInteractive(devs[0], (Disk *)devs[0]->private); 516 else 517 diskPartition(devs[0], (Disk *)devs[0]->private); 518 i = DITEM_SUCCESS; 519 } 520 else { 521 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 522 if (!menu) { 523 msgConfirm("No devices suitable for installation found!\n\n" 524 "Please verify that your disk controller (and attached drives)\n" 525 "were detected properly. This can be done by pressing the\n" 526 "[Scroll Lock] key and using the Arrow keys to move back to\n" 527 "the boot messages. Press [Scroll Lock] again to return."); 528 i = DITEM_FAILURE; 529 } 530 else { 531 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 532 free(menu); 533 } 534 i = i | DITEM_RESTORE; 535 } 536 return i; 537} 538 539int 540diskPartitionWrite(dialogMenuItem *self) 541{ 542 Device **devs; 543 char *cp; 544 int i; 545 546 if ((cp = variable_get(DISK_PARTITIONED)) && strcmp(cp, "yes")) 547 return DITEM_SUCCESS; 548 else if (!cp) { 549 msgConfirm("You must partition the disk(s) before this option can be used."); 550 return DITEM_FAILURE; 551 } 552 553 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 554 if (!devs) { 555 msgConfirm("Unable to find any disks to write to??"); 556 return DITEM_FAILURE; 557 } 558 if (isDebug()) 559 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 560 561 for (i = 0; devs[i]; i++) { 562 Chunk *c1; 563 Disk *d = (Disk *)devs[i]->private; 564 565 if (!devs[i]->enabled) 566 continue; 567 568 Set_Boot_Blocks(d, boot1, boot2); 569 msgNotify("Writing partition information to drive %s", d->name); 570 if (!Fake && Write_Disk(d)) { 571 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 572 return DITEM_FAILURE; 573 } 574 /* Now scan for bad blocks, if necessary */ 575 for (c1 = d->chunks->part; c1; c1 = c1->next) { 576 if (c1->flags & CHUNK_BAD144) { 577 int ret; 578 579 msgNotify("Running bad block scan on slice %s", c1->name); 580 if (!Fake) { 581 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 582 if (ret) 583 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 584 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 585 if (ret) 586 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 587 } 588 } 589 } 590 } 591 /* Now it's not "yes", but "written" */ 592 variable_set2(DISK_PARTITIONED, "written"); 593 return DITEM_SUCCESS; 594} 595 596/* Partition a disk based wholly on which variables are set */ 597static void 598diskPartitionNonInteractive(Device *dev, Disk *d) 599{ 600 char *cp; 601 int i, sz, all_disk = 0; 602 u_char *mbrContents; 603 604 record_chunks(d); 605 cp = variable_get(VAR_GEOMETRY); 606 if (cp) { 607 msgDebug("Setting geometry from script to: %s\n", cp); 608 d->bios_cyl = strtol(cp, &cp, 0); 609 d->bios_hd = strtol(cp + 1, &cp, 0); 610 d->bios_sect = strtol(cp + 1, 0, 0); 611 } 612 613 cp = variable_get(VAR_PARTITION); 614 if (cp) { 615 if (!strcmp(cp, "free")) { 616 /* Do free disk space case */ 617 for (i = 0; chunk_info[i]; i++) { 618 /* If a chunk is at least 10MB in size, use it. */ 619 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 620 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 621 (chunk_info[i]->flags & CHUNK_ALIGN)); 622 variable_set2(DISK_PARTITIONED, "yes"); 623 break; 624 } 625 } 626 if (!chunk_info[i]) { 627 dialog_clear(); 628 msgConfirm("Unable to find any free space on this disk!"); 629 return; 630 } 631 } 632 else if (!strcmp(cp, "all")) { 633 /* Do all disk space case */ 634 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 635 636 All_FreeBSD(d, FALSE); 637 } 638 else if (!strcmp(cp, "exclusive")) { 639 /* Do really-all-the-disk-space case */ 640 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 641 642 All_FreeBSD(d, all_disk = TRUE); 643 } 644 else if ((sz = strtol(cp, &cp, 0))) { 645 /* Look for sz bytes free */ 646 if (*cp && toupper(*cp) == 'M') 647 sz *= ONE_MEG; 648 for (i = 0; chunk_info[i]; i++) { 649 /* If a chunk is at least sz MB, use it. */ 650 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 651 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 652 variable_set2(DISK_PARTITIONED, "yes"); 653 break; 654 } 655 } 656 if (!chunk_info[i]) { 657 dialog_clear(); 658 msgConfirm("Unable to find %d free blocks on this disk!", sz); 659 return; 660 } 661 } 662 else if (!strcmp(cp, "existing")) { 663 /* Do existing FreeBSD case */ 664 for (i = 0; chunk_info[i]; i++) { 665 if (chunk_info[i]->type == freebsd) 666 break; 667 } 668 if (!chunk_info[i]) { 669 dialog_clear(); 670 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 671 return; 672 } 673 } 674 else { 675 dialog_clear(); 676 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 677 return; 678 } 679 if (!all_disk) { 680 mbrContents = getBootMgr(d->name); 681 Set_Boot_Mgr(d, mbrContents); 682 } 683 variable_set2(DISK_PARTITIONED, "yes"); 684 } 685} 686