disks.c revision 39845
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.100 1998/09/15 10:24:46 gibbs 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); 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, 0, "%10s %10s %10s %8s %6s %10s %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, 0, "%10ld %10lu %10lu %8s %6d %10s %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, "T = Change Type 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 174int 175diskGetSelectCount(Device ***devs) 176{ 177 int i, cnt, enabled; 178 char *cp; 179 Device **dp; 180 181 cp = variable_get(VAR_DISK); 182 dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); 183 cnt = deviceCount(dp); 184 if (!cnt) 185 return -1; 186 for (i = 0, enabled = 0; i < cnt; i++) { 187 if (dp[i]->enabled) 188 ++enabled; 189 } 190 return enabled; 191} 192 193void 194diskPartition(Device *dev) 195{ 196 char *cp, *p; 197 int rv, key = 0; 198 Boolean chunking; 199 char *msg = NULL; 200 u_char *mbrContents; 201 WINDOW *w = savescr(); 202 Disk *d = (Disk *)dev->private; 203 204 chunking = TRUE; 205 keypad(stdscr, TRUE); 206 207 /* Flush both the dialog and curses library views of the screen 208 since we don't always know who called us */ 209 dialog_clear_norefresh(), clear(); 210 current_chunk = 0; 211 212 /* Set up the chunk array */ 213 record_chunks(d); 214 215 while (chunking) { 216 char *val, geometry[80]; 217 218 /* Now print our overall state */ 219 if (d) 220 print_chunks(d); 221 print_command_summary(); 222 if (msg) { 223 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 224 beep(); 225 msg = NULL; 226 } 227 else { 228 move(23, 0); 229 clrtoeol(); 230 } 231 232 /* Get command character */ 233 key = getch(); 234 switch (toupper(key)) { 235 case '\014': /* ^L (redraw) */ 236 clear(); 237 msg = NULL; 238 break; 239 240 case '\020': /* ^P */ 241 case KEY_UP: 242 case '-': 243 if (current_chunk != 0) 244 --current_chunk; 245 break; 246 247 case '\016': /* ^N */ 248 case KEY_DOWN: 249 case '+': 250 case '\r': 251 case '\n': 252 if (chunk_info[current_chunk + 1]) 253 ++current_chunk; 254 break; 255 256 case KEY_HOME: 257 current_chunk = 0; 258 break; 259 260 case KEY_END: 261 while (chunk_info[current_chunk + 1]) 262 ++current_chunk; 263 break; 264 265 case KEY_F(1): 266 case '?': 267 systemDisplayHelp("slice"); 268 clear(); 269 break; 270 271 case 'A': 272#ifdef __alpha__ 273 rv = 1; 274#else /* The rest is only relevant on x86 */ 275 cp = variable_get(VAR_DEDICATE_DISK); 276 if (cp && !strcasecmp(cp, "always")) 277 rv = 1; 278 else { 279 rv = msgYesNo("Do you want to do this with a true partition entry\n" 280 "so as to remain cooperative with any future possible\n" 281 "operating systems on the drive(s)?\n" 282 "(See also the section about ``dangerously dedicated''\n" 283 "disks in the FreeBSD FAQ.)"); 284 if (rv == -1) 285 rv = 0; 286 } 287#endif 288 All_FreeBSD(d, rv); 289 variable_set2(DISK_PARTITIONED, "yes"); 290 record_chunks(d); 291 clear(); 292 break; 293 294 case 'B': 295 if (chunk_info[current_chunk]->type != freebsd) 296 msg = "Can only scan for bad blocks in FreeBSD slice."; 297 else if (strncmp(d->name, "sd", 2) || 298 strncmp(d->name, "da", 2) || 299 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n" 300 "Are you sure you want to do this on a SCSI disk?")) { 301 if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 302 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 303 else 304 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 305 } 306 clear(); 307 break; 308 309 case 'C': 310 if (chunk_info[current_chunk]->type != unused) 311 msg = "Slice in use, delete it first or move to an unused one."; 312 else { 313 char *val, tmp[20], *cp; 314 int size, subtype; 315 chunk_e partitiontype; 316 317 snprintf(tmp, 20, "%lu", chunk_info[current_chunk]->size); 318 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 319 "or append a trailing `M' for megabytes (e.g. 20M)."); 320 if (val && (size = strtol(val, &cp, 0)) > 0) { 321 if (*cp && toupper(*cp) == 'M') 322 size *= ONE_MEG; 323 strcpy(tmp, "165"); 324 val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 325 "Pressing Enter will choose the default, a native FreeBSD\n" 326 "slice (type 165). You can choose other types, 6 for a\n" 327 "DOS partition or 131 for a Linux partition, for example.\n\n" 328 "Note: If you choose a non-FreeBSD partition type, it will not\n" 329 "be formatted or otherwise prepared, it will simply reserve space\n" 330 "for you to use another tool, such as DOS FORMAT, to later format\n" 331 "and use the partition."); 332 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 333 if (subtype == 165) 334 partitiontype = freebsd; 335 else if (subtype == 6) 336 partitiontype = fat; 337 else 338 partitiontype = unknown; 339 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 340 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 341 variable_set2(DISK_PARTITIONED, "yes"); 342 record_chunks(d); 343 } 344 } 345 clear(); 346 } 347 break; 348 349 case KEY_DC: 350 case 'D': 351 if (chunk_info[current_chunk]->type == unused) 352 msg = "Slice is already unused!"; 353 else { 354 Delete_Chunk(d, chunk_info[current_chunk]); 355 variable_set2(DISK_PARTITIONED, "yes"); 356 record_chunks(d); 357 } 358 break; 359 360 case 'T': 361 if (chunk_info[current_chunk]->type == unused) 362 msg = "Slice is currently unused (use create instead)"; 363 else { 364 char *val, tmp[20]; 365 int subtype; 366 chunk_e partitiontype; 367 WINDOW *save = savescr(); 368 369 strcpy(tmp, "165"); 370 val = msgGetInput(tmp, "New partition type:\n\n" 371 "Pressing Enter will choose the default, a native FreeBSD\n" 372 "slice (type 165). Other popular values are 6 for\n" 373 "DOS FAT partition, 131 for a Linux ext2fs partition or\n" 374 "130 for a Linux swap partition.\n\n" 375 "Note: If you choose a non-FreeBSD partition type, it will not\n" 376 "be formatted or otherwise prepared, it will simply reserve space\n" 377 "for you to use another tool, such as DOS format, to later format\n" 378 "and actually use the partition."); 379 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 380 if (subtype == 165) 381 partitiontype = freebsd; 382 else if (subtype == 6) 383 partitiontype = fat; 384 else 385 partitiontype = unknown; 386 chunk_info[current_chunk]->type = partitiontype; 387 chunk_info[current_chunk]->subtype = subtype; 388 } 389 restorescr(save); 390 } 391 break; 392 393 case 'G': 394 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 395 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 396 "Don't forget to use the two slash (/) separator characters!\n" 397 "It's not possible to parse the field without them."); 398 if (val) { 399 long nc, nh, ns; 400 nc = strtol(val, &val, 0); 401 nh = strtol(val + 1, &val, 0); 402 ns = strtol(val + 1, 0, 0); 403 Set_Bios_Geom(d, nc, nh, ns); 404 } 405 clear(); 406 break; 407 408 case 'S': 409 /* Set Bootable */ 410 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 411 break; 412 413 case 'U': 414 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 415 msgConfirm("You've already written this information out - you\n" 416 "can't undo it."); 417 } 418 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 419 char cp[BUFSIZ]; 420 421 sstrncpy(cp, d->name, sizeof cp); 422 Free_Disk(dev->private); 423 d = Open_Disk(cp); 424 if (!d) 425 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 426 dev->private = d; 427 variable_unset(DISK_PARTITIONED); 428 variable_unset(DISK_LABELLED); 429 if (d) 430 record_chunks(d); 431 } 432 clear(); 433 break; 434 435 case 'W': 436 if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 437 "installation. If you are installing FreeBSD for the first time\n" 438 "then you should simply type Q when you're finished here and your\n" 439 "changes will be committed in one batch automatically at the end of\n" 440 "these questions. If you're adding a disk, you should NOT write\n" 441 "from this screen, you should do it from the label editor.\n\n" 442 "Are you absolutely sure you want to do this now?")) { 443 variable_set2(DISK_PARTITIONED, "yes"); 444 445 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 446 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 447 * booteasy or a "standard" MBR -- both would be fatal in this case. 448 */ 449#if 0 450 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 451 && (mbrContents = getBootMgr(d->name)) != NULL) 452 Set_Boot_Mgr(d, mbrContents); 453#else 454 /* 455 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 456 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 457 */ 458 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 459 (mbrContents = getBootMgr(d->name)) != NULL) 460 Set_Boot_Mgr(d, mbrContents); 461#endif 462 463 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 464 msgConfirm("Disk partition write returned an error status!"); 465 else 466 msgConfirm("Wrote FDISK partition information out successfully."); 467 } 468 clear(); 469 break; 470 471 case '|': 472 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 473 "No seat belts whatsoever are provided!")) { 474 clear(); 475 refresh(); 476 slice_wizard(d); 477 variable_set2(DISK_PARTITIONED, "yes"); 478 record_chunks(d); 479 } 480 else 481 msg = "Wise choice!"; 482 clear(); 483 break; 484 485 case '\033': /* ESC */ 486 case 'Q': 487 chunking = FALSE; 488 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 489 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 490 * booteasy or a "standard" MBR -- both would be fatal in this case. 491 */ 492#if 0 493 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 494 && (mbrContents = getBootMgr(d->name)) != NULL) 495 Set_Boot_Mgr(d, mbrContents); 496#else 497 /* 498 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 499 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 500 */ 501 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 502 (mbrContents = getBootMgr(d->name)) != NULL) 503 Set_Boot_Mgr(d, mbrContents); 504#endif 505 break; 506 507 default: 508 beep(); 509 msg = "Type F1 or ? for help"; 510 break; 511 } 512 } 513 p = CheckRules(d); 514 if (p) { 515 char buf[FILENAME_MAX]; 516 517 dialog_clear_norefresh(); 518 use_helpline("Press F1 to read more about disk slices."); 519 use_helpfile(systemHelpFile("partition", buf)); 520 if (!variable_get(VAR_NO_WARN)) 521 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 522 free(p); 523 } 524 restorescr(w); 525} 526 527static int 528partitionHook(dialogMenuItem *selected) 529{ 530 Device **devs = NULL; 531 532 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 533 if (!devs) { 534 msgConfirm("Unable to find disk %s!", selected->prompt); 535 return DITEM_FAILURE; 536 } 537 /* Toggle enabled status? */ 538 if (!devs[0]->enabled) { 539 devs[0]->enabled = TRUE; 540 diskPartition(devs[0]); 541 } 542 else 543 devs[0]->enabled = FALSE; 544 return DITEM_SUCCESS | DITEM_RESTORE; 545} 546 547static int 548partitionCheck(dialogMenuItem *selected) 549{ 550 Device **devs = NULL; 551 552 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 553 if (!devs || devs[0]->enabled == FALSE) 554 return FALSE; 555 return TRUE; 556} 557 558int 559diskPartitionEditor(dialogMenuItem *self) 560{ 561 DMenu *menu; 562 Device **devs; 563 int i, cnt, devcnt; 564 565 cnt = diskGetSelectCount(&devs); 566 devcnt = deviceCount(devs); 567 if (cnt == -1) { 568 msgConfirm("No disks found! Please verify that your disk controller is being\n" 569 "properly probed at boot time. See the Hardware Guide on the\n" 570 "Documentation menu for clues on diagnosing this type of problem."); 571 return DITEM_FAILURE; 572 } 573 else if (cnt) { 574 /* Some are already selected */ 575 for (i = 0; i < devcnt; i++) { 576 if (devs[i]->enabled) { 577 if (variable_get(VAR_NONINTERACTIVE)) 578 diskPartitionNonInteractive(devs[i]); 579 else 580 diskPartition(devs[i]); 581 } 582 } 583 } 584 else { 585 /* No disks are selected, fall-back case now */ 586 if (devcnt == 1) { 587 devs[0]->enabled = TRUE; 588 if (variable_get(VAR_NONINTERACTIVE)) 589 diskPartitionNonInteractive(devs[0]); 590 else 591 diskPartition(devs[0]); 592 return DITEM_SUCCESS; 593 } 594 else { 595 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 596 if (!menu) { 597 msgConfirm("No devices suitable for installation found!\n\n" 598 "Please verify that your disk controller (and attached drives)\n" 599 "were detected properly. This can be done by pressing the\n" 600 "[Scroll Lock] key and using the Arrow keys to move back to\n" 601 "the boot messages. Press [Scroll Lock] again to return."); 602 return DITEM_FAILURE; 603 } 604 else { 605 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 606 free(menu); 607 } 608 return i | DITEM_RESTORE; 609 } 610 } 611 return DITEM_SUCCESS; 612} 613 614int 615diskPartitionWrite(dialogMenuItem *self) 616{ 617 Device **devs; 618 int i; 619 char *cp; 620 621 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 622 if (!devs) { 623 msgConfirm("Unable to find any disks to write to??"); 624 return DITEM_FAILURE; 625 } 626 if (isDebug()) 627 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 628 cp = variable_get(DISK_PARTITIONED); 629 if (cp && !strcmp(cp, "written")) 630 return DITEM_SUCCESS; 631 632 for (i = 0; devs[i]; i++) { 633 Chunk *c1; 634 Disk *d = (Disk *)devs[i]->private; 635 636 if (!devs[i]->enabled) 637 continue; 638 639 Set_Boot_Blocks(d, boot1, boot2); 640 msgNotify("Writing partition information to drive %s", d->name); 641 if (!Fake && Write_Disk(d)) { 642 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 643 return DITEM_FAILURE; 644 } 645 646 /* If we've been through here before, we don't need to do the rest */ 647 if (cp && !strcmp(cp, "written")) 648 return DITEM_SUCCESS; 649 650 /* Now scan for bad blocks, if necessary */ 651 for (c1 = d->chunks->part; c1; c1 = c1->next) { 652 if (c1->flags & CHUNK_BAD144) { 653 int ret; 654 655 msgNotify("Running bad block scan on slice %s", c1->name); 656 if (!Fake) { 657 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 658 if (ret) 659 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 660 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 661 if (ret) 662 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 663 } 664 } 665 } 666 } 667 /* Now it's not "yes", but "written" */ 668 variable_set2(DISK_PARTITIONED, "written"); 669 return DITEM_SUCCESS; 670} 671 672/* Partition a disk based wholly on which variables are set */ 673static void 674diskPartitionNonInteractive(Device *dev) 675{ 676 char *cp; 677 int i, sz, all_disk = 0; 678 u_char *mbrContents; 679 Disk *d = (Disk *)dev->private; 680 681 record_chunks(d); 682 cp = variable_get(VAR_GEOMETRY); 683 if (cp) { 684 msgDebug("Setting geometry from script to: %s\n", cp); 685 d->bios_cyl = strtol(cp, &cp, 0); 686 d->bios_hd = strtol(cp + 1, &cp, 0); 687 d->bios_sect = strtol(cp + 1, 0, 0); 688 } 689 690 cp = variable_get(VAR_PARTITION); 691 if (cp) { 692 if (!strcmp(cp, "free")) { 693 /* Do free disk space case */ 694 for (i = 0; chunk_info[i]; i++) { 695 /* If a chunk is at least 10MB in size, use it. */ 696 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 697 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 698 (chunk_info[i]->flags & CHUNK_ALIGN)); 699 variable_set2(DISK_PARTITIONED, "yes"); 700 break; 701 } 702 } 703 if (!chunk_info[i]) { 704 dialog_clear(); 705 msgConfirm("Unable to find any free space on this disk!"); 706 return; 707 } 708 } 709 else if (!strcmp(cp, "all")) { 710 /* Do all disk space case */ 711 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 712 713 All_FreeBSD(d, FALSE); 714 } 715 else if (!strcmp(cp, "exclusive")) { 716 /* Do really-all-the-disk-space case */ 717 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 718 719 All_FreeBSD(d, all_disk = TRUE); 720 } 721 else if ((sz = strtol(cp, &cp, 0))) { 722 /* Look for sz bytes free */ 723 if (*cp && toupper(*cp) == 'M') 724 sz *= ONE_MEG; 725 for (i = 0; chunk_info[i]; i++) { 726 /* If a chunk is at least sz MB, use it. */ 727 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 728 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 729 variable_set2(DISK_PARTITIONED, "yes"); 730 break; 731 } 732 } 733 if (!chunk_info[i]) { 734 dialog_clear(); 735 msgConfirm("Unable to find %d free blocks on this disk!", sz); 736 return; 737 } 738 } 739 else if (!strcmp(cp, "existing")) { 740 /* Do existing FreeBSD case */ 741 for (i = 0; chunk_info[i]; i++) { 742 if (chunk_info[i]->type == freebsd) 743 break; 744 } 745 if (!chunk_info[i]) { 746 dialog_clear(); 747 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 748 return; 749 } 750 } 751 else { 752 dialog_clear(); 753 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 754 return; 755 } 756 if (!all_disk) { 757 mbrContents = getBootMgr(d->name); 758 Set_Boot_Mgr(d, mbrContents); 759 } 760 variable_set2(DISK_PARTITIONED, "yes"); 761 } 762} 763