disks.c revision 39847
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.101 1998/09/30 21:48:11 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); 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#ifdef __alpha__ 340 if (partitiontype == freebsd && size == chunk_info[current_chunk]->size) 341 All_FreeBSD(d, 1); 342 else 343#endif 344 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 345 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 346 variable_set2(DISK_PARTITIONED, "yes"); 347 record_chunks(d); 348 } 349 } 350 clear(); 351 } 352 break; 353 354 case KEY_DC: 355 case 'D': 356 if (chunk_info[current_chunk]->type == unused) 357 msg = "Slice is already unused!"; 358 else { 359 Delete_Chunk(d, chunk_info[current_chunk]); 360 variable_set2(DISK_PARTITIONED, "yes"); 361 record_chunks(d); 362 } 363 break; 364 365 case 'T': 366 if (chunk_info[current_chunk]->type == unused) 367 msg = "Slice is currently unused (use create instead)"; 368 else { 369 char *val, tmp[20]; 370 int subtype; 371 chunk_e partitiontype; 372 WINDOW *save = savescr(); 373 374 strcpy(tmp, "165"); 375 val = msgGetInput(tmp, "New partition type:\n\n" 376 "Pressing Enter will choose the default, a native FreeBSD\n" 377 "slice (type 165). Other popular values are 6 for\n" 378 "DOS FAT partition, 131 for a Linux ext2fs partition or\n" 379 "130 for a Linux swap partition.\n\n" 380 "Note: If you choose a non-FreeBSD partition type, it will not\n" 381 "be formatted or otherwise prepared, it will simply reserve space\n" 382 "for you to use another tool, such as DOS format, to later format\n" 383 "and actually use the partition."); 384 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 385 if (subtype == 165) 386 partitiontype = freebsd; 387 else if (subtype == 6) 388 partitiontype = fat; 389 else 390 partitiontype = unknown; 391 chunk_info[current_chunk]->type = partitiontype; 392 chunk_info[current_chunk]->subtype = subtype; 393 } 394 restorescr(save); 395 } 396 break; 397 398 case 'G': 399 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 400 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 401 "Don't forget to use the two slash (/) separator characters!\n" 402 "It's not possible to parse the field without them."); 403 if (val) { 404 long nc, nh, ns; 405 nc = strtol(val, &val, 0); 406 nh = strtol(val + 1, &val, 0); 407 ns = strtol(val + 1, 0, 0); 408 Set_Bios_Geom(d, nc, nh, ns); 409 } 410 clear(); 411 break; 412 413 case 'S': 414 /* Set Bootable */ 415 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 416 break; 417 418 case 'U': 419 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 420 msgConfirm("You've already written this information out - you\n" 421 "can't undo it."); 422 } 423 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 424 char cp[BUFSIZ]; 425 426 sstrncpy(cp, d->name, sizeof cp); 427 Free_Disk(dev->private); 428 d = Open_Disk(cp); 429 if (!d) 430 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 431 dev->private = d; 432 variable_unset(DISK_PARTITIONED); 433 variable_unset(DISK_LABELLED); 434 if (d) 435 record_chunks(d); 436 } 437 clear(); 438 break; 439 440 case 'W': 441 if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 442 "installation. If you are installing FreeBSD for the first time\n" 443 "then you should simply type Q when you're finished here and your\n" 444 "changes will be committed in one batch automatically at the end of\n" 445 "these questions. If you're adding a disk, you should NOT write\n" 446 "from this screen, you should do it from the label editor.\n\n" 447 "Are you absolutely sure you want to do this now?")) { 448 variable_set2(DISK_PARTITIONED, "yes"); 449 450 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 451 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 452 * booteasy or a "standard" MBR -- both would be fatal in this case. 453 */ 454#if 0 455 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 456 && (mbrContents = getBootMgr(d->name)) != NULL) 457 Set_Boot_Mgr(d, mbrContents); 458#else 459 /* 460 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 461 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 462 */ 463 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 464 (mbrContents = getBootMgr(d->name)) != NULL) 465 Set_Boot_Mgr(d, mbrContents); 466#endif 467 468 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 469 msgConfirm("Disk partition write returned an error status!"); 470 else 471 msgConfirm("Wrote FDISK partition information out successfully."); 472 } 473 clear(); 474 break; 475 476 case '|': 477 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 478 "No seat belts whatsoever are provided!")) { 479 clear(); 480 refresh(); 481 slice_wizard(d); 482 variable_set2(DISK_PARTITIONED, "yes"); 483 record_chunks(d); 484 } 485 else 486 msg = "Wise choice!"; 487 clear(); 488 break; 489 490 case '\033': /* ESC */ 491 case 'Q': 492 chunking = FALSE; 493 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 494 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 495 * booteasy or a "standard" MBR -- both would be fatal in this case. 496 */ 497#if 0 498 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 499 && (mbrContents = getBootMgr(d->name)) != NULL) 500 Set_Boot_Mgr(d, mbrContents); 501#else 502 /* 503 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 504 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 505 */ 506 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 507 (mbrContents = getBootMgr(d->name)) != NULL) 508 Set_Boot_Mgr(d, mbrContents); 509#endif 510 break; 511 512 default: 513 beep(); 514 msg = "Type F1 or ? for help"; 515 break; 516 } 517 } 518 p = CheckRules(d); 519 if (p) { 520 char buf[FILENAME_MAX]; 521 522 dialog_clear_norefresh(); 523 use_helpline("Press F1 to read more about disk slices."); 524 use_helpfile(systemHelpFile("partition", buf)); 525 if (!variable_get(VAR_NO_WARN)) 526 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 527 free(p); 528 } 529 restorescr(w); 530} 531 532static int 533partitionHook(dialogMenuItem *selected) 534{ 535 Device **devs = NULL; 536 537 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 538 if (!devs) { 539 msgConfirm("Unable to find disk %s!", selected->prompt); 540 return DITEM_FAILURE; 541 } 542 /* Toggle enabled status? */ 543 if (!devs[0]->enabled) { 544 devs[0]->enabled = TRUE; 545 diskPartition(devs[0]); 546 } 547 else 548 devs[0]->enabled = FALSE; 549 return DITEM_SUCCESS | DITEM_RESTORE; 550} 551 552static int 553partitionCheck(dialogMenuItem *selected) 554{ 555 Device **devs = NULL; 556 557 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 558 if (!devs || devs[0]->enabled == FALSE) 559 return FALSE; 560 return TRUE; 561} 562 563int 564diskPartitionEditor(dialogMenuItem *self) 565{ 566 DMenu *menu; 567 Device **devs; 568 int i, cnt, devcnt; 569 570 cnt = diskGetSelectCount(&devs); 571 devcnt = deviceCount(devs); 572 if (cnt == -1) { 573 msgConfirm("No disks found! Please verify that your disk controller is being\n" 574 "properly probed at boot time. See the Hardware Guide on the\n" 575 "Documentation menu for clues on diagnosing this type of problem."); 576 return DITEM_FAILURE; 577 } 578 else if (cnt) { 579 /* Some are already selected */ 580 for (i = 0; i < devcnt; i++) { 581 if (devs[i]->enabled) { 582 if (variable_get(VAR_NONINTERACTIVE)) 583 diskPartitionNonInteractive(devs[i]); 584 else 585 diskPartition(devs[i]); 586 } 587 } 588 } 589 else { 590 /* No disks are selected, fall-back case now */ 591 if (devcnt == 1) { 592 devs[0]->enabled = TRUE; 593 if (variable_get(VAR_NONINTERACTIVE)) 594 diskPartitionNonInteractive(devs[0]); 595 else 596 diskPartition(devs[0]); 597 return DITEM_SUCCESS; 598 } 599 else { 600 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 601 if (!menu) { 602 msgConfirm("No devices suitable for installation found!\n\n" 603 "Please verify that your disk controller (and attached drives)\n" 604 "were detected properly. This can be done by pressing the\n" 605 "[Scroll Lock] key and using the Arrow keys to move back to\n" 606 "the boot messages. Press [Scroll Lock] again to return."); 607 return DITEM_FAILURE; 608 } 609 else { 610 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 611 free(menu); 612 } 613 return i | DITEM_RESTORE; 614 } 615 } 616 return DITEM_SUCCESS; 617} 618 619int 620diskPartitionWrite(dialogMenuItem *self) 621{ 622 Device **devs; 623 int i; 624 char *cp; 625 626 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 627 if (!devs) { 628 msgConfirm("Unable to find any disks to write to??"); 629 return DITEM_FAILURE; 630 } 631 if (isDebug()) 632 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 633 cp = variable_get(DISK_PARTITIONED); 634 if (cp && !strcmp(cp, "written")) 635 return DITEM_SUCCESS; 636 637 for (i = 0; devs[i]; i++) { 638 Chunk *c1; 639 Disk *d = (Disk *)devs[i]->private; 640 641 if (!devs[i]->enabled) 642 continue; 643 644 Set_Boot_Blocks(d, boot1, boot2); 645 msgNotify("Writing partition information to drive %s", d->name); 646 if (!Fake && Write_Disk(d)) { 647 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 648 return DITEM_FAILURE; 649 } 650 651 /* If we've been through here before, we don't need to do the rest */ 652 if (cp && !strcmp(cp, "written")) 653 return DITEM_SUCCESS; 654 655 /* Now scan for bad blocks, if necessary */ 656 for (c1 = d->chunks->part; c1; c1 = c1->next) { 657 if (c1->flags & CHUNK_BAD144) { 658 int ret; 659 660 msgNotify("Running bad block scan on slice %s", c1->name); 661 if (!Fake) { 662 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 663 if (ret) 664 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 665 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 666 if (ret) 667 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 668 } 669 } 670 } 671 } 672 /* Now it's not "yes", but "written" */ 673 variable_set2(DISK_PARTITIONED, "written"); 674 return DITEM_SUCCESS; 675} 676 677/* Partition a disk based wholly on which variables are set */ 678static void 679diskPartitionNonInteractive(Device *dev) 680{ 681 char *cp; 682 int i, sz, all_disk = 0; 683 u_char *mbrContents; 684 Disk *d = (Disk *)dev->private; 685 686 record_chunks(d); 687 cp = variable_get(VAR_GEOMETRY); 688 if (cp) { 689 msgDebug("Setting geometry from script to: %s\n", cp); 690 d->bios_cyl = strtol(cp, &cp, 0); 691 d->bios_hd = strtol(cp + 1, &cp, 0); 692 d->bios_sect = strtol(cp + 1, 0, 0); 693 } 694 695 cp = variable_get(VAR_PARTITION); 696 if (cp) { 697 if (!strcmp(cp, "free")) { 698 /* Do free disk space case */ 699 for (i = 0; chunk_info[i]; i++) { 700 /* If a chunk is at least 10MB in size, use it. */ 701 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 702 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 703 (chunk_info[i]->flags & CHUNK_ALIGN)); 704 variable_set2(DISK_PARTITIONED, "yes"); 705 break; 706 } 707 } 708 if (!chunk_info[i]) { 709 dialog_clear(); 710 msgConfirm("Unable to find any free space on this disk!"); 711 return; 712 } 713 } 714 else if (!strcmp(cp, "all")) { 715 /* Do all disk space case */ 716 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 717 718 All_FreeBSD(d, FALSE); 719 } 720 else if (!strcmp(cp, "exclusive")) { 721 /* Do really-all-the-disk-space case */ 722 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 723 724 All_FreeBSD(d, all_disk = TRUE); 725 } 726 else if ((sz = strtol(cp, &cp, 0))) { 727 /* Look for sz bytes free */ 728 if (*cp && toupper(*cp) == 'M') 729 sz *= ONE_MEG; 730 for (i = 0; chunk_info[i]; i++) { 731 /* If a chunk is at least sz MB, use it. */ 732 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 733 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 734 variable_set2(DISK_PARTITIONED, "yes"); 735 break; 736 } 737 } 738 if (!chunk_info[i]) { 739 dialog_clear(); 740 msgConfirm("Unable to find %d free blocks on this disk!", sz); 741 return; 742 } 743 } 744 else if (!strcmp(cp, "existing")) { 745 /* Do existing FreeBSD case */ 746 for (i = 0; chunk_info[i]; i++) { 747 if (chunk_info[i]->type == freebsd) 748 break; 749 } 750 if (!chunk_info[i]) { 751 dialog_clear(); 752 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 753 return; 754 } 755 } 756 else { 757 dialog_clear(); 758 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 759 return; 760 } 761 if (!all_disk) { 762 mbrContents = getBootMgr(d->name); 763 Set_Boot_Mgr(d, mbrContents); 764 } 765 variable_set2(DISK_PARTITIONED, "yes"); 766 } 767} 768