disks.c revision 25665
176195Sbrian/* 276195Sbrian * The new sysinstall program. 376358Sbrian * 476358Sbrian * This is probably the last program in the `sysinstall' line - the next 576358Sbrian * generation being essentially a complete rewrite. 676195Sbrian * 776195Sbrian * $Id: disks.c,v 1.84 1997/05/05 05:16:00 pst Exp $ 876195Sbrian * 976195Sbrian * Copyright (c) 1995 1076195Sbrian * Jordan Hubbard. All rights reserved. 1176195Sbrian * 1276195Sbrian * Redistribution and use in source and binary forms, with or without 1376195Sbrian * modification, are permitted provided that the following conditions 1476195Sbrian * are met: 1576195Sbrian * 1. Redistributions of source code must retain the above copyright 1676195Sbrian * notice, this list of conditions and the following disclaimer, 1776195Sbrian * verbatim and that no modifications are made prior to this 1876195Sbrian * point in the file. 1976195Sbrian * 2. Redistributions in binary form must reproduce the above copyright 2076195Sbrian * notice, this list of conditions and the following disclaimer in the 2176195Sbrian * documentation and/or other materials provided with the distribution. 2276195Sbrian * 2376195Sbrian * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2476195Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2576195Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2676195Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 2776195Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2876195Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2976195Sbrian * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3076195Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3176195Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3276195Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3376195Sbrian * SUCH DAMAGE. 3476195Sbrian * 3576195Sbrian */ 3676195Sbrian 3776195Sbrian#include "sysinstall.h" 3876195Sbrian#include <ctype.h> 3976195Sbrian#include <sys/disklabel.h> 4076195Sbrian 4176195Sbrian/* Where we start displaying chunk information on the screen */ 4276195Sbrian#define CHUNK_START_ROW 5 43119277Simp 4476195Sbrian/* Where we keep track of MBR chunks */ 4576848Sbrianstatic struct chunk *chunk_info[16]; 4676853Sbrianstatic int current_chunk; 4776853Sbrian 4876853Sbrianstatic void 4976195Sbrianrecord_chunks(Disk *d) 5076195Sbrian{ 5176195Sbrian struct chunk *c1 = NULL; 5276195Sbrian int i = 0; 5376195Sbrian int last_free = 0; 5476195Sbrian 5576195Sbrian if (!d->chunks) 5676195Sbrian msgFatal("No chunk list found for %s!", d->name); 5776195Sbrian 5876195Sbrian for (c1 = d->chunks->part; c1; c1 = c1->next) { 5976195Sbrian if (c1->type == unused && c1->size > last_free) { 6076195Sbrian last_free = c1->size; 6176195Sbrian current_chunk = i; 6276195Sbrian } 6376195Sbrian chunk_info[i++] = c1; 6476195Sbrian } 6576195Sbrian chunk_info[i] = NULL; 6676195Sbrian if (current_chunk >= i) 6776195Sbrian current_chunk = i - 1; 6876195Sbrian} 6976195Sbrian 7076195Sbrianstatic int Total; 7176195Sbrian 7276195Sbrianstatic void 7376195Sbrianprint_chunks(Disk *d) 7476195Sbrian{ 7576195Sbrian int row; 7676195Sbrian int i; 7776195Sbrian 7876195Sbrian for (i = Total = 0; chunk_info[i]; i++) 7976195Sbrian Total += chunk_info[i]->size; 8076195Sbrian if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { 8176195Sbrian dialog_clear_norefresh(); 8276195Sbrian msgConfirm("WARNING: A geometry of %d/%d/%d for %s is incorrect. Using\n" 8376195Sbrian "a more likely geometry. If this geometry is incorrect or you\n" 8476195Sbrian "are unsure as to whether or not it's correct, please consult\n" 8576195Sbrian "the Hardware Guide in the Documentation submenu or use the\n" 8676195Sbrian "(G)eometry command to change it now.\n\n" 8776195Sbrian "Remember: you need to enter whatever your BIOS thinks the\n" 8876195Sbrian "geometry is! For IDE, it's what you were told in the BIOS\n" 8976195Sbrian "setup. For SCSI, it's the translation mode your controller is\n" 9076195Sbrian "using. Do NOT use a ``physical geometry''.", 9176195Sbrian d->bios_cyl, d->bios_hd, d->bios_sect, d->name); 9276358Sbrian Sanitize_Bios_Geom(d); 9376195Sbrian } 9476195Sbrian attrset(A_NORMAL); 9576358Sbrian mvaddstr(0, 0, "Disk name:\t"); 9676195Sbrian clrtobot(); 9776195Sbrian attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 9876195Sbrian attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 9976195Sbrian mvprintw(1, 0, 10076195Sbrian "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %lu sectors", 10176195Sbrian d->bios_cyl, d->bios_hd, d->bios_sect, 10276195Sbrian d->bios_cyl * d->bios_hd * d->bios_sect); 10376195Sbrian mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", 10476195Sbrian "Offset", "Size", "End", "Name", "PType", "Desc", 10576195Sbrian "Subtype", "Flags"); 10676195Sbrian for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 10776195Sbrian if (i == current_chunk) 10876195Sbrian attrset(ATTR_SELECTED); 10976195Sbrian mvprintw(row, 2, "%10ld %10lu %10lu %8s %8d %8s %8d\t%-6s", 11076195Sbrian chunk_info[i]->offset, chunk_info[i]->size, 11176195Sbrian chunk_info[i]->end, chunk_info[i]->name, 11276195Sbrian chunk_info[i]->type, 11376195Sbrian slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), 11476195Sbrian chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 11576195Sbrian if (i == current_chunk) 11676195Sbrian attrset(A_NORMAL); 11776195Sbrian } 11876195Sbrian} 11976195Sbrian 12076195Sbrianstatic void 12176195Sbrianprint_command_summary() 12276195Sbrian{ 12376195Sbrian mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 12476195Sbrian mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Slice"); 12576195Sbrian mvprintw(17, 0, "D = Delete Slice G = Set Drive Geometry S = Set Bootable"); 12676195Sbrian mvprintw(18, 0, "U = Undo All Changes Q = Finish"); 12776195Sbrian if (!RunningAsInit) 12876195Sbrian mvprintw(18, 48, "W = Write Changes"); 12976195Sbrian mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); 13076195Sbrian move(0, 0); 13176195Sbrian} 13276195Sbrian 13376195Sbrianstatic u_char * 13476195SbriangetBootMgr(char *dname) 13576195Sbrian{ 13676195Sbrian extern u_char mbr[], bteasy17[]; 13776195Sbrian char str[80]; 13876195Sbrian char *cp; 13976195Sbrian int i = 0; 14076195Sbrian 14176195Sbrian cp = variable_get(VAR_BOOTMGR); 14276195Sbrian if (!cp) { 14376195Sbrian /* Figure out what kind of MBR the user wants */ 14476195Sbrian sprintf(str, "Install Boot Manager for drive %s?", dname); 14576195Sbrian MenuMBRType.title = str; 14676195Sbrian i = dmenuOpenSimple(&MenuMBRType, FALSE); 14776195Sbrian } 14876195Sbrian else { 14976195Sbrian if (!strncmp(cp, "boot", 4)) 15076195Sbrian BootMgr = 0; 15176195Sbrian else if (!strcmp(cp, "standard")) 15276195Sbrian BootMgr = 1; 15376195Sbrian else 15476195Sbrian BootMgr = 2; 15576195Sbrian } 15676195Sbrian if (cp || i) { 15776195Sbrian switch (BootMgr) { 15876195Sbrian case 0: 15976195Sbrian return bteasy17; 16076195Sbrian 16176195Sbrian case 1: 16276195Sbrian return mbr; 16376195Sbrian 16476195Sbrian case 2: 16576195Sbrian default: 16676195Sbrian break; 16776195Sbrian } 16876195Sbrian } 16976195Sbrian return NULL; 17076195Sbrian} 17176195Sbrian 17276195Sbrianvoid 17376195SbriandiskPartition(Device *dev, Disk *d) 17476195Sbrian{ 17576195Sbrian char *cp, *p; 17676195Sbrian int rv, key = 0; 17776195Sbrian Boolean chunking; 17876195Sbrian char *msg = NULL; 17976195Sbrian u_char *mbrContents; 18076195Sbrian WINDOW *w = savescr(); 18176195Sbrian 18276195Sbrian chunking = TRUE; 18376195Sbrian keypad(stdscr, TRUE); 18476195Sbrian 18576195Sbrian /* Flush both the dialog and curses library views of the screen 18676195Sbrian since we don't always know who called us */ 18776195Sbrian dialog_clear_norefresh(), clear(); 18876358Sbrian current_chunk = 0; 18976195Sbrian 19076195Sbrian /* Set up the chunk array */ 19176195Sbrian record_chunks(d); 19276195Sbrian 19376195Sbrian while (chunking) { 19476195Sbrian char *val, geometry[80]; 19576195Sbrian 19676195Sbrian /* Now print our overall state */ 19776195Sbrian if (d) 19876195Sbrian print_chunks(d); 19976195Sbrian print_command_summary(); 20076195Sbrian if (msg) { 20176195Sbrian attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 20276195Sbrian beep(); 20376195Sbrian msg = NULL; 20476195Sbrian } 20576195Sbrian else { 20676195Sbrian move(23, 0); 20776195Sbrian clrtoeol(); 20876195Sbrian } 20976195Sbrian 21076195Sbrian /* Get command character */ 21176195Sbrian key = getch(); 21276195Sbrian switch (toupper(key)) { 21376195Sbrian case '\014': /* ^L (redraw) */ 21476195Sbrian clear(); 21576195Sbrian msg = NULL; 21676195Sbrian break; 21776195Sbrian 21876195Sbrian case '\020': /* ^P */ 21976195Sbrian case KEY_UP: 22076195Sbrian case '-': 22176195Sbrian if (current_chunk != 0) 22276195Sbrian --current_chunk; 22376195Sbrian break; 22476195Sbrian 22576195Sbrian case '\016': /* ^N */ 22676195Sbrian case KEY_DOWN: 22776195Sbrian case '+': 22891445Speter case '\r': 229 case '\n': 230 if (chunk_info[current_chunk + 1]) 231 ++current_chunk; 232 break; 233 234 case KEY_HOME: 235 current_chunk = 0; 236 break; 237 238 case KEY_END: 239 while (chunk_info[current_chunk + 1]) 240 ++current_chunk; 241 break; 242 243 case KEY_F(1): 244 case '?': 245 systemDisplayHelp("slice"); 246 clear(); 247 break; 248 249 case 'A': 250 cp = variable_get(VAR_DEDICATE_DISK); 251 if (cp && !strcasecmp(cp, "always")) 252 rv = 1; 253 else { 254 rv = msgYesNo("Do you want to do this with a true partition entry\n" 255 "so as to remain cooperative with any future possible\n" 256 "operating systems on the drive(s)?"); 257 if (rv != 0 && (!cp || strcasecmp(cp, "nowarn"))) { 258 rv = !msgYesNo("This is dangerous in that it will make the drive totally\n" 259 "uncooperative with other potential operating systems on the\n" 260 "same disk. It will lead instead to a totally dedicated disk,\n" 261 "starting at the very first sector, bypassing all BIOS geometry\n" 262 "considerations. This precludes the existance of any boot\n" 263 "manager or other stuff in sector 0, since the BSD bootstrap\n" 264 "will live there.\n" 265 "You will run into serious trouble with ST-506 and ESDI drives\n" 266 "and possibly some IDE drives (e.g. drives running under the\n" 267 "control of sort of disk manager). SCSI drives are considerably\n" 268 "less at risk.\n\n" 269 "If, on the other hand, your goal is a dedicated FreeBSD machine\n" 270 "and nothing else, this option is for you.\n\n" 271 "Do you insist on dedicating the entire disk this way?"); 272 } 273 if (rv == -1) 274 rv = 0; 275 } 276 All_FreeBSD(d, rv); 277 variable_set2(DISK_PARTITIONED, "yes"); 278 record_chunks(d); 279 clear(); 280 break; 281 282 case 'B': 283 if (chunk_info[current_chunk]->type != freebsd) 284 msg = "Can only scan for bad blocks in FreeBSD slice."; 285 else if (strncmp(d->name, "sd", 2) || 286 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n" 287 "Are you sure you want to do this on a SCSI disk?")) { 288 if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 289 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 290 else 291 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 292 } 293 clear(); 294 break; 295 296 case 'C': 297 if (chunk_info[current_chunk]->type != unused) 298 msg = "Slice in use, delete it first or move to an unused one."; 299 else { 300 char *val, tmp[20], *cp; 301 int size, subtype; 302 chunk_e partitiontype; 303 304 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); 305 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 306 "or append a trailing `M' for megabytes (e.g. 20M)."); 307 if (val && (size = strtol(val, &cp, 0)) > 0) { 308 if (*cp && toupper(*cp) == 'M') 309 size *= ONE_MEG; 310 strcpy(tmp, "165"); 311 val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 312 "Pressing Enter will choose the default, a native FreeBSD\n" 313 "slice (type 165). You can choose other types, 6 for a\n" 314 "DOS partition or 131 for a Linux partition, for example.\n\n" 315 "Note: If you choose a non-FreeBSD partition type, it will not\n" 316 "be formatted or otherwise prepared, it will simply reserve space\n" 317 "for you to use another tool, such as DOS FORMAT, to later format\n" 318 "and use the partition."); 319 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 320 if (subtype==165) 321 partitiontype=freebsd; 322 else if (subtype==6) 323 partitiontype=fat; 324 else 325 partitiontype=unknown; 326 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 327 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 328 variable_set2(DISK_PARTITIONED, "yes"); 329 record_chunks(d); 330 } 331 } 332 clear(); 333 } 334 break; 335 336 case KEY_DC: 337 case 'D': 338 if (chunk_info[current_chunk]->type == unused) 339 msg = "Slice is already unused!"; 340 else { 341 Delete_Chunk(d, chunk_info[current_chunk]); 342 variable_set2(DISK_PARTITIONED, "yes"); 343 record_chunks(d); 344 } 345 break; 346 347 case 'G': 348 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 349 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 350 "Don't forget to use the two slash (/) separator characters!\n" 351 "It's not possible to parse the field without them."); 352 if (val) { 353 long nc, nh, ns; 354 nc = strtol(val, &val, 0); 355 nh = strtol(val + 1, &val, 0); 356 ns = strtol(val + 1, 0, 0); 357 Set_Bios_Geom(d, nc, nh, ns); 358 } 359 clear(); 360 break; 361 362 case 'S': 363 /* Set Bootable */ 364 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 365 break; 366 367 case 'U': 368 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 369 msgConfirm("You've already written this information out - you\n" 370 "can't undo it."); 371 } 372 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 373 char cp[BUFSIZ]; 374 375 sstrncpy(cp, d->name, sizeof cp); 376 Free_Disk(dev->private); 377 d = Open_Disk(cp); 378 if (!d) 379 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 380 dev->private = d; 381 variable_unset(DISK_PARTITIONED); 382 variable_unset(DISK_LABELLED); 383 if (d) 384 record_chunks(d); 385 } 386 clear(); 387 break; 388 389 case 'W': 390 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 391 msgConfirm("You've already written this information out - if\n" 392 "you wish to overwrite it, you'll have to restart."); 393 } 394 else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 395 "installation. If you are installing FreeBSD for the first time\n" 396 "then you should simply type Q when you're finished here and your\n" 397 "changes will be committed in one batch automatically at the end of\n" 398 "these questions.\n\n" 399 "Are you absolutely sure you want to do this now?")) { 400 variable_set2(DISK_PARTITIONED, "yes"); 401 402 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 403 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 404 * booteasy or a "standard" MBR -- both would be fatal in this case. 405 */ 406 if (!(d->chunks->part->flags & CHUNK_FORCE_ALL) && (mbrContents = getBootMgr(d->name)) != NULL) 407 Set_Boot_Mgr(d, mbrContents); 408 409 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 410 msgConfirm("Disk partition write returned an error status!"); 411 else 412 msgConfirm("Wrote FDISK partition information out successfully."); 413 } 414 clear(); 415 break; 416 417 case '|': 418 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 419 "No seat belts whatsoever are provided!")) { 420 clear(); 421 refresh(); 422 slice_wizard(d); 423 variable_set2(DISK_PARTITIONED, "yes"); 424 record_chunks(d); 425 } 426 else 427 msg = "Wise choice!"; 428 clear(); 429 break; 430 431 case '\033': /* ESC */ 432 case 'Q': 433 chunking = FALSE; 434 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 435 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 436 * booteasy or a "standard" MBR -- both would be fatal in this case. 437 */ 438 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 439 && (mbrContents = getBootMgr(d->name)) != NULL) 440 Set_Boot_Mgr(d, mbrContents); 441 break; 442 443 default: 444 beep(); 445 msg = "Type F1 or ? for help"; 446 break; 447 } 448 } 449 p = CheckRules(d); 450 if (p) { 451 char buf[FILENAME_MAX]; 452 453 dialog_clear_norefresh(); 454 use_helpline("Press F1 to read more about disk slices."); 455 use_helpfile(systemHelpFile("partition", buf)); 456 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 457 free(p); 458 } 459 restorescr(w); 460} 461 462static int 463partitionHook(dialogMenuItem *selected) 464{ 465 Device **devs = NULL; 466 467 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 468 if (!devs) { 469 msgConfirm("Unable to find disk %s!", selected->prompt); 470 return DITEM_FAILURE; 471 } 472 /* Toggle enabled status? */ 473 if (!devs[0]->enabled) { 474 devs[0]->enabled = TRUE; 475 diskPartition(devs[0], (Disk *)devs[0]->private); 476 } 477 else 478 devs[0]->enabled = FALSE; 479 return DITEM_SUCCESS | DITEM_REDRAW; 480} 481 482static int 483partitionCheck(dialogMenuItem *selected) 484{ 485 Device **devs = NULL; 486 487 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 488 if (!devs || devs[0]->enabled == FALSE) 489 return FALSE; 490 return TRUE; 491} 492 493int 494diskPartitionEditor(dialogMenuItem *self) 495{ 496 DMenu *menu; 497 Device **devs; 498 int i, cnt; 499 char *cp; 500 501 cp = variable_get(VAR_DISK); 502 devs = deviceFind(cp, DEVICE_TYPE_DISK); 503 cnt = deviceCount(devs); 504 if (!cnt) { 505 msgConfirm("No disks found! Please verify that your disk controller is being\n" 506 "properly probed at boot time. See the Hardware Guide on the\n" 507 "Documentation menu for clues on diagnosing this type of problem."); 508 i = DITEM_FAILURE; 509 } 510 else if (cnt == 1) { 511 devs[0]->enabled = TRUE; 512 diskPartition(devs[0], (Disk *)devs[0]->private); 513 i = DITEM_SUCCESS; 514 } 515 else { 516 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 517 if (!menu) { 518 msgConfirm("No devices suitable for installation found!\n\n" 519 "Please verify that your disk controller (and attached drives)\n" 520 "were detected properly. This can be done by pressing the\n" 521 "[Scroll Lock] key and using the Arrow keys to move back to\n" 522 "the boot messages. Press [Scroll Lock] again to return."); 523 i = DITEM_FAILURE; 524 } 525 else { 526 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 527 free(menu); 528 } 529 i = i | DITEM_RESTORE; 530 } 531 return i; 532} 533 534int 535diskPartitionWrite(dialogMenuItem *self) 536{ 537 Device **devs; 538 char *cp; 539 int i; 540 541 if ((cp = variable_get(DISK_PARTITIONED)) && strcmp(cp, "yes")) 542 return DITEM_SUCCESS; 543 else if (!cp) { 544 msgConfirm("You must partition the disk(s) before this option can be used."); 545 return DITEM_FAILURE; 546 } 547 548 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 549 if (!devs) { 550 msgConfirm("Unable to find any disks to write to??"); 551 return DITEM_FAILURE; 552 } 553 if (isDebug()) 554 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 555 556 for (i = 0; devs[i]; i++) { 557 Chunk *c1; 558 Disk *d = (Disk *)devs[i]->private; 559 560 if (!devs[i]->enabled) 561 continue; 562 563 Set_Boot_Blocks(d, boot1, boot2); 564 msgNotify("Writing partition information to drive %s", d->name); 565 if (!Fake && Write_Disk(d)) { 566 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 567 return DITEM_FAILURE; 568 } 569 /* Now scan for bad blocks, if necessary */ 570 for (c1 = d->chunks->part; c1; c1 = c1->next) { 571 if (c1->flags & CHUNK_BAD144) { 572 int ret; 573 574 msgNotify("Running bad block scan on slice %s", c1->name); 575 if (!Fake) { 576 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 577 if (ret) 578 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 579 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 580 if (ret) 581 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 582 } 583 } 584 } 585 } 586 /* Now it's not "yes", but "written" */ 587 variable_set2(DISK_PARTITIONED, "written"); 588 return DITEM_SUCCESS; 589} 590