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