label.c revision 15442
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: label.c,v 1.46 1996/04/28 22:54:18 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#include <sys/param.h> 41#include <sys/sysctl.h> 42 43/* 44 * Everything to do with editing the contents of disk labels. 45 */ 46 47/* A nice message we use a lot in the disklabel editor */ 48#define MSG_NOT_APPLICABLE "That option is not applicable here" 49 50/* Where to start printing the freebsd slices */ 51#define CHUNK_SLICE_START_ROW 2 52#define CHUNK_PART_START_ROW 11 53 54/* The smallest filesystem we're willing to create */ 55#define FS_MIN_SIZE ONE_MEG 56 57/* The smallest root filesystem we're willing to create */ 58#define ROOT_MIN_SIZE 20 59 60/* The smallest swap partition we want to create by default */ 61#define SWAP_MIN_SIZE 16 62 63/* The smallest /usr partition we're willing to create by default */ 64#define USR_MIN_SIZE 80 65 66/* The smallest /var partition we're willing to create by default */ 67#define VAR_MIN_SIZE 30 68 69/* The bottom-most row we're allowed to scribble on */ 70#define CHUNK_ROW_MAX 16 71 72 73/* All the chunks currently displayed on the screen */ 74static struct { 75 struct chunk *c; 76 PartType type; 77} label_chunk_info[MAX_CHUNKS + 1]; 78static int here; 79 80static int ChunkPartStartRow; 81static WINDOW *ChunkWin; 82 83static int diskLabel(char *str); 84 85int 86diskLabelEditor(dialogMenuItem *self) 87{ 88 Device **devs; 89 int i, cnt, enabled; 90 char *cp; 91 92 cp = variable_get(VAR_DISK); 93 devs = deviceFind(cp, DEVICE_TYPE_DISK); 94 cnt = deviceCount(devs); 95 if (!cnt) { 96 msgConfirm("No disks found! Please verify that your disk controller is being\n" 97 "properly probed at boot time. See the Hardware Guide on the\n" 98 "Documentation menu for clues on diagnosing this type of problem."); 99 return DITEM_FAILURE; 100 } 101 for (i = 0, enabled = 0; i < cnt; i++) { 102 if (devs[i]->enabled) 103 ++enabled; 104 } 105 if (!enabled) { 106 devs[0]->enabled = TRUE; 107 if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE) 108 return DITEM_FAILURE; 109 } 110 i = diskLabel(devs[0]->name); 111 if (DITEM_STATUS(i) != DITEM_FAILURE) 112 variable_set2(DISK_LABELLED, "yes"); 113 return i; 114} 115 116int 117diskLabelCommit(dialogMenuItem *self) 118{ 119 char *cp; 120 int i; 121 122 /* Already done? */ 123 if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) { 124 variable_set2(DISK_PARTITIONED, "yes"); 125 i = DITEM_SUCCESS; 126 } 127 else if (!cp) { 128 msgConfirm("You must assign disk labels before this option can be used."); 129 i = DITEM_FAILURE; 130 } 131 /* The routine will guard against redundant writes, just as this one does */ 132 else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 133 i = DITEM_FAILURE; 134 else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 135 i = DITEM_FAILURE; 136 else { 137 msgInfo("All filesystem information written successfully."); 138 variable_set2(DISK_LABELLED, "written"); 139 i = DITEM_SUCCESS; 140 } 141 return i; 142} 143 144/* See if we're already using a desired partition name */ 145static Boolean 146check_conflict(char *name) 147{ 148 int i; 149 150 for (i = 0; label_chunk_info[i].c; i++) 151 if (label_chunk_info[i].type == PART_FILESYSTEM && label_chunk_info[i].c->private_data 152 && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 153 return TRUE; 154 return FALSE; 155} 156 157/* How much space is in this FreeBSD slice? */ 158static int 159space_free(struct chunk *c) 160{ 161 struct chunk *c1; 162 int sz = c->size; 163 164 for (c1 = c->part; c1; c1 = c1->next) { 165 if (c1->type != unused) 166 sz -= c1->size; 167 } 168 if (sz < 0) 169 msgFatal("Partitions are larger than actual chunk??"); 170 return sz; 171} 172 173/* Snapshot the current situation into the displayed chunks structure */ 174static void 175record_label_chunks(Device **devs) 176{ 177 int i, j, p; 178 struct chunk *c1, *c2; 179 Disk *d; 180 181 ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3; 182 j = p = 0; 183 /* First buzz through and pick up the FreeBSD slices */ 184 for (i = 0; devs[i]; i++) { 185 if (!devs[i]->enabled) 186 continue; 187 d = (Disk *)devs[i]->private; 188 if (!d->chunks) 189 msgFatal("No chunk list found for %s!", d->name); 190 191 /* Put the slice entries first */ 192 for (c1 = d->chunks->part; c1; c1 = c1->next) { 193 if (c1->type == freebsd) { 194 label_chunk_info[j].type = PART_SLICE; 195 label_chunk_info[j].c = c1; 196 ++j; 197 ++ChunkPartStartRow; 198 } 199 } 200 } 201 202 /* Now run through again and get the FreeBSD partition entries */ 203 for (i = 0; devs[i]; i++) { 204 if (!devs[i]->enabled) 205 continue; 206 d = (Disk *)devs[i]->private; 207 /* Then buzz through and pick up the partitions */ 208 for (c1 = d->chunks->part; c1; c1 = c1->next) { 209 if (c1->type == freebsd) { 210 for (c2 = c1->part; c2; c2 = c2->next) { 211 if (c2->type == part) { 212 if (c2->subtype == FS_SWAP) 213 label_chunk_info[j].type = PART_SWAP; 214 else 215 label_chunk_info[j].type = PART_FILESYSTEM; 216 label_chunk_info[j].c = c2; 217 ++j; 218 } 219 } 220 } 221 else if (c1->type == fat) { 222 label_chunk_info[j].type = PART_FAT; 223 label_chunk_info[j].c = c1; 224 ++j; 225 } 226 } 227 } 228 label_chunk_info[j].c = NULL; 229 if (here >= j) 230 here = j ? j - 1 : 0; 231 if (ChunkWin) { 232 wclear(ChunkWin); 233 wrefresh(ChunkWin); 234 } 235 else 236 ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 237} 238 239/* A new partition entry */ 240static PartInfo * 241new_part(char *mpoint, Boolean newfs, u_long size) 242{ 243 PartInfo *ret; 244 u_long target, divisor; 245 246 if (!mpoint) 247 mpoint = "/change_me"; 248 249 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 250 strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 251 strcpy(ret->newfs_cmd, "newfs -b 8192 -f 1024"); 252 ret->newfs = newfs; 253 if (!size) 254 return ret; 255 for (target = size; target; target--) { 256 for (divisor = 4096 ; divisor > 1023; divisor--) { 257 if (!(target % divisor)) { 258 sprintf(ret->newfs_cmd + strlen(ret->newfs_cmd), " -u %ld",divisor); 259 return ret; 260 } 261 } 262 } 263 return ret; 264} 265 266/* Get the mountpoint for a partition and save it away */ 267static PartInfo * 268get_mountpoint(struct chunk *old) 269{ 270 char *val; 271 PartInfo *tmp; 272 273 if (old && old->private_data) 274 tmp = old->private_data; 275 else 276 tmp = NULL; 277 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 278 if (!val || !*val) { 279 if (!old) 280 return NULL; 281 else { 282 free(old->private_data); 283 old->private_data = NULL; 284 } 285 return NULL; 286 } 287 288 /* Is it just the same value? */ 289 if (tmp && !strcmp(tmp->mountpoint, val)) 290 return NULL; 291 292 /* Did we use it already? */ 293 if (check_conflict(val)) { 294 msgConfirm("You already have a mount point for %s assigned!", val); 295 return NULL; 296 } 297 298 /* Is it bogus? */ 299 if (*val != '/') { 300 msgConfirm("Mount point must start with a / character"); 301 return NULL; 302 } 303 304 /* Is it going to be mounted on root? */ 305 if (!strcmp(val, "/")) { 306 if (old) 307 old->flags |= CHUNK_IS_ROOT; 308 } 309 else if (old) 310 old->flags &= ~CHUNK_IS_ROOT; 311 312 safe_free(tmp); 313 tmp = new_part(val, TRUE, 0); 314 if (old) { 315 old->private_data = tmp; 316 old->private_free = safe_free; 317 } 318 return tmp; 319} 320 321/* Get the type of the new partiton */ 322static PartType 323get_partition_type(void) 324{ 325 char selection[20]; 326 int i; 327 WINDOW *w = savescr(); 328 329 static unsigned char *fs_types[] = { 330 "FS", 331 "A file system", 332 "Swap", 333 "A swap partition.", 334 }; 335 i = dialog_menu("Please choose a partition type", 336 "If you want to use this partition for swap space, select Swap.\n" 337 "If you want to put a filesystem on it, choose FS.", 338 -1, -1, 2, 2, fs_types, selection, NULL, NULL); 339 restorescr(w); 340 if (!i) { 341 if (!strcmp(selection, "FS")) 342 return PART_FILESYSTEM; 343 else if (!strcmp(selection, "Swap")) 344 return PART_SWAP; 345 } 346 return PART_NONE; 347} 348 349/* If the user wants a special newfs command for this, set it */ 350static void 351getNewfsCmd(PartInfo *p) 352{ 353 char *val; 354 355 val = msgGetInput(p->newfs_cmd, 356 "Please enter the newfs command and options you'd like to use in\n" 357 "creating this file system."); 358 if (val) 359 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 360} 361 362#define MAX_MOUNT_NAME 12 363 364#define PART_PART_COL 0 365#define PART_MOUNT_COL 8 366#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 367#define PART_NEWFS_COL (PART_SIZE_COL + 7) 368#define PART_OFF 38 369 370/* stick this all up on the screen */ 371static void 372print_label_chunks(void) 373{ 374 int i, j, srow, prow, pcol; 375 int sz; 376 377 attrset(A_REVERSE); 378 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 379 attrset(A_NORMAL); 380 381 for (i = 0; i < 2; i++) { 382 mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 383 mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 384 385 mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 386 mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 387 388 mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 389 mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 390 391 mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 392 mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 393 } 394 srow = CHUNK_SLICE_START_ROW; 395 prow = 0; 396 pcol = 0; 397 398 for (i = 0; label_chunk_info[i].c; i++) { 399 /* Is it a slice entry displayed at the top? */ 400 if (label_chunk_info[i].type == PART_SLICE) { 401 sz = space_free(label_chunk_info[i].c); 402 if (i == here) 403 attrset(A_REVERSE); 404 mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 405 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, sz, (sz / ONE_MEG)); 406 attrset(A_NORMAL); 407 clrtoeol(); 408 move(0, 0); 409 refresh(); 410 } 411 /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 412 else { 413 char onestr[PART_OFF], num[10], *mountpoint, *newfs; 414 415 /* 416 * We copy this into a blank-padded string so that it looks like 417 * a solid bar in reverse-video 418 */ 419 memset(onestr, ' ', PART_OFF - 1); 420 onestr[PART_OFF - 1] = '\0'; 421 /* Go for two columns if we've written one full columns worth */ 422 if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) { 423 pcol = PART_OFF; 424 prow = 0; 425 } 426 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 427 /* If it's a filesystem, display the mountpoint */ 428 if (label_chunk_info[i].c->private_data 429 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 430 mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 431 else 432 mountpoint = "<none>"; 433 434 /* Now display the newfs field */ 435 if (label_chunk_info[i].type == PART_FAT) 436 newfs = "DOS"; 437 else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) 438 newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N"; 439 else if (label_chunk_info[i].type == PART_SWAP) 440 newfs = "SWAP"; 441 else 442 newfs = "*"; 443 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 444 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 445 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 446 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 447 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 448 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 449 if (i == here) 450 wattrset(ChunkWin, A_REVERSE); 451 mvwaddstr(ChunkWin, prow, pcol, onestr); 452 wattrset(ChunkWin, A_NORMAL); 453 wrefresh(ChunkWin); 454 move(0, 0); 455 ++prow; 456 } 457 } 458} 459 460static void 461print_command_summary() 462{ 463 mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 464 mvprintw(18, 0, "C = Create D = Delete M = Mount"); 465 if (!RunningAsInit) 466 mvprintw(18, 48, "W = Write"); 467 mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish"); 468 mvprintw(20, 0, "A = Auto Defaults for all!"); 469 mvprintw(22, 0, "The default target will be displayed in "); 470 471 attrset(A_REVERSE); 472 addstr("reverse"); 473 attrset(A_NORMAL); 474 addstr(" video."); 475 mvprintw(23, 0, "Use F1 or ? to get more help, arrow keys to move."); 476 move(0, 0); 477} 478 479static int 480diskLabel(char *str) 481{ 482 int sz, key = 0, first_time = 1; 483 Boolean labeling; 484 char *msg = NULL; 485 PartInfo *p, *oldp; 486 PartType type; 487 Device **devs; 488 WINDOW *w; 489 490 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 491 if (!devs) { 492 msgConfirm("No disks found!"); 493 return DITEM_FAILURE; 494 } 495 496 labeling = TRUE; 497 keypad(stdscr, TRUE); 498 record_label_chunks(devs); 499 500 w = savescr(); 501 dialog_clear(); clear(); 502 while (labeling) { 503 print_label_chunks(); 504 if (first_time) { 505 print_command_summary(); 506 first_time = 0; 507 } 508 if (msg) { 509 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 510 clrtoeol(); 511 beep(); 512 msg = NULL; 513 } 514 else { 515 move(23, 0); 516 clrtoeol(); 517 } 518 key = toupper(getch()); 519 switch (key) { 520 int i; 521 522 case '\014': /* ^L */ 523 continue; 524 525 case KEY_UP: 526 case '-': 527 if (here != 0) 528 --here; 529 else 530 while (label_chunk_info[here + 1].c) 531 ++here; 532 break; 533 534 case KEY_DOWN: 535 case '+': 536 case '\r': 537 case '\n': 538 if (label_chunk_info[here + 1].c) 539 ++here; 540 else 541 here = 0; 542 break; 543 544 case KEY_HOME: 545 here = 0; 546 break; 547 548 case KEY_END: 549 while (label_chunk_info[here + 1].c) 550 ++here; 551 break; 552 553 case KEY_F(1): 554 case '?': 555 systemDisplayHelp("partition"); 556 break; 557 558 case 'A': 559 if (label_chunk_info[here].type != PART_SLICE) { 560 msg = "You can only do this in a disk slice (at top of screen)"; 561 break; 562 } 563 sz = space_free(label_chunk_info[here].c); 564 if (sz <= FS_MIN_SIZE) { 565 msg = "Not enough free space to create a new partition in the slice"; 566 break; 567 } 568 else { 569 struct chunk *tmp; 570 int mib[2]; 571 int physmem; 572 size_t size, swsize; 573 char *cp; 574 575 cp = variable_get(VAR_ROOT_SIZE); 576 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 577 label_chunk_info[here].c, 578 (cp ? atoi(cp) : 32) * ONE_MEG, part, FS_BSDFFS, 579 CHUNK_IS_ROOT); 580 581 if (!tmp) { 582 msgConfirm("Unable to create the root partition. Too big?"); 583 break; 584 } 585 tmp->private_data = new_part("/", TRUE, tmp->size); 586 tmp->private_free = safe_free; 587 record_label_chunks(devs); 588 589 cp = variable_get(VAR_SWAP_SIZE); 590 if (cp) 591 swsize = atoi(cp) * ONE_MEG; 592 else { 593 mib[0] = CTL_HW; 594 mib[1] = HW_PHYSMEM; 595 size = sizeof physmem; 596 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 597 swsize = 16 * ONE_MEG + (physmem * 2 / 512); 598 } 599 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 600 label_chunk_info[here].c, 601 swsize, 602 part, FS_SWAP, 0); 603 if (!tmp) { 604 msgConfirm("Unable to create the swap partition. Too big?"); 605 break; 606 } 607 608 tmp->private_data = 0; 609 tmp->private_free = safe_free; 610 record_label_chunks(devs); 611 612 cp = variable_get(VAR_VAR_SIZE); 613 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 614 label_chunk_info[here].c, 615 (cp ? atoi(cp) : VAR_MIN_SIZE) * ONE_MEG, part, FS_BSDFFS, 0); 616 if (!tmp) { 617 msgConfirm("Less than %dMB free for /var - you will need to\n" 618 "partition your disk manually with a custom install!", (cp ? atoi(cp) : VAR_MIN_SIZE)); 619 break; 620 } 621 tmp->private_data = new_part("/var", TRUE, tmp->size); 622 tmp->private_free = safe_free; 623 record_label_chunks(devs); 624 625 cp = variable_get(VAR_USR_SIZE); 626 if (cp) 627 sz = atoi(cp) * ONE_MEG; 628 else 629 sz = space_free(label_chunk_info[here].c); 630 if (!sz || sz < (USR_MIN_SIZE * ONE_MEG)) { 631 msgConfirm("Less than %dMB free for /usr - you will need to\n" 632 "partition your disk manually with a custom install!", USR_MIN_SIZE); 633 break; 634 } 635 636 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 637 label_chunk_info[here].c, 638 sz, part, FS_BSDFFS, 0); 639 if (!tmp) { 640 msgConfirm("Unable to create the /usr partition. Not enough space?\n" 641 "You will need to partition your disk manually with a custom install!"); 642 break; 643 } 644 /* At this point, we're reasonably "labelled" */ 645 variable_set2(DISK_LABELLED, "yes"); 646 tmp->private_data = new_part("/usr", TRUE, tmp->size); 647 tmp->private_free = safe_free; 648 record_label_chunks(devs); 649 } 650 break; 651 652 case 'C': 653 if (label_chunk_info[here].type != PART_SLICE) { 654 msg = "You can only do this in a master partition (see top of screen)"; 655 break; 656 } 657 sz = space_free(label_chunk_info[here].c); 658 if (sz <= FS_MIN_SIZE) { 659 msg = "Not enough space to create an additional FreeBSD partition"; 660 break; 661 } 662 else { 663 char *val, *cp; 664 int size; 665 struct chunk *tmp; 666 char osize[80]; 667 u_long flags = 0; 668 669 sprintf(osize, "%d", sz); 670 val = msgGetInput(osize, "Please specify the size for new FreeBSD partition in blocks, or\n" 671 "append a trailing `M' for megabytes (e.g. 20M) or `C' for cylinders.\n\n" 672 "Space free is %d blocks (%dMB)", sz, sz / ONE_MEG); 673 if (!val || (size = strtol(val, &cp, 0)) <= 0) 674 break; 675 676 if (*cp) { 677 if (toupper(*cp) == 'M') 678 size *= ONE_MEG; 679 else if (toupper(*cp) == 'C') 680 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 681 } 682 if (size <= FS_MIN_SIZE) { 683 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 684 break; 685 } 686 type = get_partition_type(); 687 if (type == PART_NONE) 688 break; 689 690 if (type == PART_FILESYSTEM) { 691 if ((p = get_mountpoint(NULL)) == NULL) 692 break; 693 else if (!strcmp(p->mountpoint, "/")) 694 flags |= CHUNK_IS_ROOT; 695 else 696 flags &= ~CHUNK_IS_ROOT; 697 } else 698 p = NULL; 699 700 if ((flags & CHUNK_IS_ROOT)) { 701 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 702 msgConfirm("This region cannot be used for your root partition as the\n" 703 "FreeBSD boot code cannot deal with a root partition created\n" 704 "in that location. Please choose another location or smaller\n" 705 "size for your root partition and try again!"); 706 break; 707 } 708 if (size < (ROOT_MIN_SIZE * ONE_MEG)) { 709 msgConfirm("Warning: This is smaller than the recommended size for a\n" 710 "root partition. For a variety of reasons, root\n" 711 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 712 } 713 } 714 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 715 label_chunk_info[here].c, 716 size, part, 717 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 718 flags); 719 if (!tmp) { 720 msgConfirm("Unable to create the partition. Too big?"); 721 break; 722 } 723 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 724 msgConfirm("This region cannot be used for your root partition as it starts\n" 725 "or extends past the 1024'th cylinder mark and is thus a\n" 726 "poor location to boot from. Please choose another\n" 727 "location (or smaller size) for your root partition and try again!"); 728 Delete_Chunk(label_chunk_info[here].c->disk, tmp); 729 break; 730 } 731 if (type != PART_SWAP) { 732 /* This is needed to tell the newfs -u about the size */ 733 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 734 tmp->private_free = safe_free; 735 safe_free(p); 736 } 737 else 738 tmp->private_data = p; 739 tmp->private_free = safe_free; 740 variable_set2(DISK_LABELLED, "yes"); 741 record_label_chunks(devs); 742 } 743 break; 744 745 case '\177': 746 case 'D': /* delete */ 747 if (label_chunk_info[here].type == PART_SLICE) { 748 msg = MSG_NOT_APPLICABLE; 749 break; 750 } 751 else if (label_chunk_info[here].type == PART_FAT) { 752 msg = "Use the Disk Partition Editor to delete DOS partitions"; 753 break; 754 } 755 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 756 variable_set2(DISK_LABELLED, "yes"); 757 record_label_chunks(devs); 758 break; 759 760 case 'M': /* mount */ 761 switch(label_chunk_info[here].type) { 762 case PART_SLICE: 763 msg = MSG_NOT_APPLICABLE; 764 break; 765 766 case PART_SWAP: 767 msg = "You don't need to specify a mountpoint for a swap partition."; 768 break; 769 770 case PART_FAT: 771 case PART_FILESYSTEM: 772 oldp = label_chunk_info[here].c->private_data; 773 p = get_mountpoint(label_chunk_info[here].c); 774 if (p) { 775 if (!oldp) 776 p->newfs = FALSE; 777 if (label_chunk_info[here].type == PART_FAT 778 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 779 || !strcmp(p->mountpoint, "/var"))) { 780 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 781 strcpy(p->mountpoint, "/bogus"); 782 } 783 } 784 variable_set2(DISK_LABELLED, "yes"); 785 record_label_chunks(devs); 786 break; 787 788 default: 789 msgFatal("Bogus partition under cursor???"); 790 break; 791 } 792 break; 793 794 case 'N': /* Set newfs options */ 795 if (label_chunk_info[here].c->private_data && 796 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 797 getNewfsCmd(label_chunk_info[here].c->private_data); 798 else 799 msg = MSG_NOT_APPLICABLE; 800 break; 801 802 case 'T': /* Toggle newfs state */ 803 if (label_chunk_info[here].type == PART_FILESYSTEM) { 804 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 805 label_chunk_info[here].c->private_data = 806 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 807 safe_free(pi); 808 label_chunk_info[here].c->private_free = safe_free; 809 variable_set2(DISK_LABELLED, "yes"); 810 } 811 else 812 msg = MSG_NOT_APPLICABLE; 813 break; 814 815 case 'U': 816 clear(); 817 if (msgYesNo("Are you SURE you want to Undo everything?")) 818 break; 819 variable_unset(DISK_PARTITIONED); 820 for (i = 0; devs[i]; i++) { 821 Disk *d; 822 823 if (!devs[i]->enabled) 824 continue; 825 else if ((d = Open_Disk(devs[i]->name)) != NULL) { 826 Free_Disk(devs[i]->private); 827 devs[i]->private = d; 828 diskPartition(devs[i], d); 829 } 830 } 831 variable_unset(DISK_LABELLED); 832 record_label_chunks(devs); 833 break; 834 835 case 'W': 836 if (!msgYesNo("You also have the option of doing this later in one final 'commit'\n" 837 "operation, and it should also be noted that this option is NOT for\n" 838 "use during new installations but rather for modifying existing ones.\n\n" 839 "Are you absolutely SURE you want to do this now?")) { 840 variable_set2(DISK_LABELLED, "yes"); 841 diskLabelCommit(NULL); 842 } 843 break; 844 845 case '|': 846 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 847 "This is an entirely undocumented feature which you are not\n" 848 "expected to understand!")) { 849 int i; 850 Device **devs; 851 WINDOW *save = savescr(); 852 853 dialog_clear(); 854 end_dialog(); 855 DialogActive = FALSE; 856 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 857 if (!devs) { 858 msgConfirm("Can't find any disk devices!"); 859 break; 860 } 861 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 862 if (devs[i]->enabled) 863 slice_wizard(((Disk *)devs[i]->private)); 864 } 865 variable_set2(DISK_LABELLED, "yes"); 866 DialogActive = TRUE; 867 dialog_clear(); 868 restorescr(save); 869 record_label_chunks(devs); 870 } 871 else 872 msg = "A most prudent choice!"; 873 break; 874 875 case 'Q': 876 labeling = FALSE; 877 break; 878 879 default: 880 beep(); 881 msg = "Type F1 or ? for help"; 882 break; 883 } 884 } 885 restorescr(w); 886 return DITEM_SUCCESS; 887} 888