label.c revision 16208
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.49 1996/06/08 08:01:51 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 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(ATTR_SELECTED); 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, ATTR_SELECTED); 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, 47, "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, "Use F1 or ? to get more help, arrow keys to select."); 470 move(0, 0); 471} 472 473static int 474diskLabel(char *str) 475{ 476 int sz, key = 0, first_time = 1; 477 Boolean labeling; 478 char *msg = NULL; 479 PartInfo *p, *oldp; 480 PartType type; 481 Device **devs; 482 WINDOW *w; 483 484 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 485 if (!devs) { 486 msgConfirm("No disks found!"); 487 return DITEM_FAILURE; 488 } 489 490 labeling = TRUE; 491 keypad(stdscr, TRUE); 492 record_label_chunks(devs); 493 494 w = savescr(); 495 dialog_clear(); clear(); 496 while (labeling) { 497 print_label_chunks(); 498 if (first_time) { 499 print_command_summary(); 500 first_time = 0; 501 } 502 if (msg) { 503 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 504 clrtoeol(); 505 beep(); 506 msg = NULL; 507 } 508 else { 509 move(23, 0); 510 clrtoeol(); 511 } 512 key = toupper(getch()); 513 switch (key) { 514 int i; 515 516 case '\014': /* ^L */ 517 continue; 518 519 case KEY_UP: 520 case '-': 521 if (here != 0) 522 --here; 523 else 524 while (label_chunk_info[here + 1].c) 525 ++here; 526 break; 527 528 case KEY_DOWN: 529 case '+': 530 case '\r': 531 case '\n': 532 if (label_chunk_info[here + 1].c) 533 ++here; 534 else 535 here = 0; 536 break; 537 538 case KEY_HOME: 539 here = 0; 540 break; 541 542 case KEY_END: 543 while (label_chunk_info[here + 1].c) 544 ++here; 545 break; 546 547 case KEY_F(1): 548 case '?': 549 systemDisplayHelp("partition"); 550 break; 551 552 case 'A': 553 if (label_chunk_info[here].type != PART_SLICE) { 554 msg = "You can only do this in a disk slice (at top of screen)"; 555 break; 556 } 557 sz = space_free(label_chunk_info[here].c); 558 if (sz <= FS_MIN_SIZE) { 559 msg = "Not enough free space to create a new partition in the slice"; 560 break; 561 } 562 else { 563 struct chunk *tmp; 564 int mib[2]; 565 int physmem; 566 size_t size, swsize; 567 char *cp; 568 569 cp = variable_get(VAR_ROOT_SIZE); 570 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 571 label_chunk_info[here].c, 572 (cp ? atoi(cp) : 32) * ONE_MEG, part, FS_BSDFFS, 573 CHUNK_IS_ROOT); 574 575 if (!tmp) { 576 msgConfirm("Unable to create the root partition. Too big?"); 577 break; 578 } 579 tmp->private_data = new_part("/", TRUE, tmp->size); 580 tmp->private_free = safe_free; 581 record_label_chunks(devs); 582 583 cp = variable_get(VAR_SWAP_SIZE); 584 if (cp) 585 swsize = atoi(cp) * ONE_MEG; 586 else { 587 mib[0] = CTL_HW; 588 mib[1] = HW_PHYSMEM; 589 size = sizeof physmem; 590 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 591 swsize = 16 * ONE_MEG + (physmem * 2 / 512); 592 } 593 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 594 label_chunk_info[here].c, 595 swsize, 596 part, FS_SWAP, 0); 597 if (!tmp) { 598 msgConfirm("Unable to create the swap partition. Too big?"); 599 break; 600 } 601 602 tmp->private_data = 0; 603 tmp->private_free = safe_free; 604 record_label_chunks(devs); 605 606 cp = variable_get(VAR_VAR_SIZE); 607 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 608 label_chunk_info[here].c, 609 (cp ? atoi(cp) : VAR_MIN_SIZE) * ONE_MEG, part, FS_BSDFFS, 0); 610 if (!tmp) { 611 msgConfirm("Less than %dMB free for /var - you will need to\n" 612 "partition your disk manually with a custom install!", (cp ? atoi(cp) : VAR_MIN_SIZE)); 613 break; 614 } 615 tmp->private_data = new_part("/var", TRUE, tmp->size); 616 tmp->private_free = safe_free; 617 record_label_chunks(devs); 618 619 cp = variable_get(VAR_USR_SIZE); 620 if (cp) 621 sz = atoi(cp) * ONE_MEG; 622 else 623 sz = space_free(label_chunk_info[here].c); 624 if (!sz || sz < (USR_MIN_SIZE * ONE_MEG)) { 625 msgConfirm("Less than %dMB free for /usr - you will need to\n" 626 "partition your disk manually with a custom install!", USR_MIN_SIZE); 627 break; 628 } 629 630 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 631 label_chunk_info[here].c, 632 sz, part, FS_BSDFFS, 0); 633 if (!tmp) { 634 msgConfirm("Unable to create the /usr partition. Not enough space?\n" 635 "You will need to partition your disk manually with a custom install!"); 636 break; 637 } 638 /* At this point, we're reasonably "labelled" */ 639 variable_set2(DISK_LABELLED, "yes"); 640 tmp->private_data = new_part("/usr", TRUE, tmp->size); 641 tmp->private_free = safe_free; 642 record_label_chunks(devs); 643 } 644 break; 645 646 case 'C': 647 if (label_chunk_info[here].type != PART_SLICE) { 648 msg = "You can only do this in a master partition (see top of screen)"; 649 break; 650 } 651 sz = space_free(label_chunk_info[here].c); 652 if (sz <= FS_MIN_SIZE) { 653 msg = "Not enough space to create an additional FreeBSD partition"; 654 break; 655 } 656 else { 657 char *val, *cp; 658 int size; 659 struct chunk *tmp; 660 char osize[80]; 661 u_long flags = 0; 662 663 sprintf(osize, "%d", sz); 664 val = msgGetInput(osize, "Please specify the size for new FreeBSD partition in blocks, or\n" 665 "append a trailing `M' for megabytes (e.g. 20M) or `C' for cylinders.\n\n" 666 "Space free is %d blocks (%dMB)", sz, sz / ONE_MEG); 667 if (!val || (size = strtol(val, &cp, 0)) <= 0) 668 break; 669 670 if (*cp) { 671 if (toupper(*cp) == 'M') 672 size *= ONE_MEG; 673 else if (toupper(*cp) == 'C') 674 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 675 } 676 if (size <= FS_MIN_SIZE) { 677 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 678 break; 679 } 680 type = get_partition_type(); 681 if (type == PART_NONE) 682 break; 683 684 if (type == PART_FILESYSTEM) { 685 if ((p = get_mountpoint(NULL)) == NULL) 686 break; 687 else if (!strcmp(p->mountpoint, "/")) 688 flags |= CHUNK_IS_ROOT; 689 else 690 flags &= ~CHUNK_IS_ROOT; 691 } else 692 p = NULL; 693 694 if ((flags & CHUNK_IS_ROOT)) { 695 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 696 msgConfirm("This region cannot be used for your root partition as the\n" 697 "FreeBSD boot code cannot deal with a root partition created\n" 698 "in that location. Please choose another location or smaller\n" 699 "size for your root partition and try again!"); 700 break; 701 } 702 if (size < (ROOT_MIN_SIZE * ONE_MEG)) { 703 msgConfirm("Warning: This is smaller than the recommended size for a\n" 704 "root partition. For a variety of reasons, root\n" 705 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 706 } 707 } 708 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 709 label_chunk_info[here].c, 710 size, part, 711 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 712 flags); 713 if (!tmp) { 714 msgConfirm("Unable to create the partition. Too big?"); 715 break; 716 } 717 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 718 msgConfirm("This region cannot be used for your root partition as it starts\n" 719 "or extends past the 1024'th cylinder mark and is thus a\n" 720 "poor location to boot from. Please choose another\n" 721 "location (or smaller size) for your root partition and try again!"); 722 Delete_Chunk(label_chunk_info[here].c->disk, tmp); 723 break; 724 } 725 if (type != PART_SWAP) { 726 /* This is needed to tell the newfs -u about the size */ 727 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 728 tmp->private_free = safe_free; 729 safe_free(p); 730 } 731 else 732 tmp->private_data = p; 733 tmp->private_free = safe_free; 734 variable_set2(DISK_LABELLED, "yes"); 735 record_label_chunks(devs); 736 } 737 break; 738 739 case '\177': 740 case 'D': /* delete */ 741 if (label_chunk_info[here].type == PART_SLICE) { 742 msg = MSG_NOT_APPLICABLE; 743 break; 744 } 745 else if (label_chunk_info[here].type == PART_FAT) { 746 msg = "Use the Disk Partition Editor to delete DOS partitions"; 747 break; 748 } 749 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 750 variable_set2(DISK_LABELLED, "yes"); 751 record_label_chunks(devs); 752 break; 753 754 case 'M': /* mount */ 755 switch(label_chunk_info[here].type) { 756 case PART_SLICE: 757 msg = MSG_NOT_APPLICABLE; 758 break; 759 760 case PART_SWAP: 761 msg = "You don't need to specify a mountpoint for a swap partition."; 762 break; 763 764 case PART_FAT: 765 case PART_FILESYSTEM: 766 oldp = label_chunk_info[here].c->private_data; 767 p = get_mountpoint(label_chunk_info[here].c); 768 if (p) { 769 if (!oldp) 770 p->newfs = FALSE; 771 if (label_chunk_info[here].type == PART_FAT 772 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 773 || !strcmp(p->mountpoint, "/var"))) { 774 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 775 strcpy(p->mountpoint, "/bogus"); 776 } 777 } 778 variable_set2(DISK_LABELLED, "yes"); 779 record_label_chunks(devs); 780 break; 781 782 default: 783 msgFatal("Bogus partition under cursor???"); 784 break; 785 } 786 break; 787 788 case 'N': /* Set newfs options */ 789 if (label_chunk_info[here].c->private_data && 790 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 791 getNewfsCmd(label_chunk_info[here].c->private_data); 792 else 793 msg = MSG_NOT_APPLICABLE; 794 break; 795 796 case 'T': /* Toggle newfs state */ 797 if (label_chunk_info[here].type == PART_FILESYSTEM) { 798 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 799 label_chunk_info[here].c->private_data = 800 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 801 safe_free(pi); 802 label_chunk_info[here].c->private_free = safe_free; 803 variable_set2(DISK_LABELLED, "yes"); 804 } 805 else 806 msg = MSG_NOT_APPLICABLE; 807 break; 808 809 case 'U': 810 clear(); 811 if (msgYesNo("Are you SURE you want to Undo everything?")) 812 break; 813 variable_unset(DISK_PARTITIONED); 814 for (i = 0; devs[i]; i++) { 815 Disk *d; 816 817 if (!devs[i]->enabled) 818 continue; 819 else if ((d = Open_Disk(devs[i]->name)) != NULL) { 820 Free_Disk(devs[i]->private); 821 devs[i]->private = d; 822 diskPartition(devs[i], d); 823 } 824 } 825 variable_unset(DISK_LABELLED); 826 record_label_chunks(devs); 827 break; 828 829 case 'W': 830 if (!msgYesNo("You also have the option of doing this later in one final 'commit'\n" 831 "operation, and it should also be noted that this option is NOT for\n" 832 "use during new installations but rather for modifying existing ones.\n\n" 833 "Are you absolutely SURE you want to do this now?")) { 834 WINDOW *save = savescr(); 835 836 variable_set2(DISK_LABELLED, "yes"); 837 diskLabelCommit(NULL); 838 restorescr(save); 839 } 840 break; 841 842 case '|': 843 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 844 "This is an entirely undocumented feature which you are not\n" 845 "expected to understand!")) { 846 int i; 847 Device **devs; 848 WINDOW *save = savescr(); 849 850 dialog_clear(); 851 end_dialog(); 852 DialogActive = FALSE; 853 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 854 if (!devs) { 855 msgConfirm("Can't find any disk devices!"); 856 break; 857 } 858 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 859 if (devs[i]->enabled) 860 slice_wizard(((Disk *)devs[i]->private)); 861 } 862 variable_set2(DISK_LABELLED, "yes"); 863 DialogActive = TRUE; 864 dialog_clear(); 865 restorescr(save); 866 record_label_chunks(devs); 867 } 868 else 869 msg = "A most prudent choice!"; 870 break; 871 872 case 'Q': 873 labeling = FALSE; 874 break; 875 876 default: 877 beep(); 878 msg = "Type F1 or ? for help"; 879 break; 880 } 881 } 882 restorescr(w); 883 return DITEM_SUCCESS; 884} 885