label.c revision 18619
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.58 1996/08/03 10:11:10 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 243 if (!mpoint) 244 mpoint = "/change_me"; 245 246 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 247 strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 248 strcpy(ret->newfs_cmd, "newfs -b 8192 -f 1024"); 249 ret->newfs = newfs; 250 if (!size) 251 return ret; 252 return ret; 253} 254 255/* Get the mountpoint for a partition and save it away */ 256static PartInfo * 257get_mountpoint(struct chunk *old) 258{ 259 char *val; 260 PartInfo *tmp; 261 262 if (old && old->private_data) 263 tmp = old->private_data; 264 else 265 tmp = NULL; 266 if (!old) { 267 DialogX = 13; 268 DialogY = 17; 269 } 270 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 271 DialogX = DialogY = 0; 272 if (!val || !*val) { 273 if (!old) 274 return NULL; 275 else { 276 free(old->private_data); 277 old->private_data = NULL; 278 } 279 return NULL; 280 } 281 282 /* Is it just the same value? */ 283 if (tmp && !strcmp(tmp->mountpoint, val)) 284 return NULL; 285 286 /* Did we use it already? */ 287 if (check_conflict(val)) { 288 msgConfirm("You already have a mount point for %s assigned!", val); 289 return NULL; 290 } 291 292 /* Is it bogus? */ 293 if (*val != '/') { 294 msgConfirm("Mount point must start with a / character"); 295 return NULL; 296 } 297 298 /* Is it going to be mounted on root? */ 299 if (!strcmp(val, "/")) { 300 if (old) 301 old->flags |= CHUNK_IS_ROOT; 302 } 303 else if (old) 304 old->flags &= ~CHUNK_IS_ROOT; 305 306 safe_free(tmp); 307 tmp = new_part(val, TRUE, 0); 308 if (old) { 309 old->private_data = tmp; 310 old->private_free = safe_free; 311 } 312 return tmp; 313} 314 315/* Get the type of the new partiton */ 316static PartType 317get_partition_type(void) 318{ 319 char selection[20]; 320 int i; 321 322 static unsigned char *fs_types[] = { 323 "FS", 324 "A file system", 325 "Swap", 326 "A swap partition.", 327 }; 328 DialogX = 7; 329 DialogY = 9; 330 i = dialog_menu("Please choose a partition type", 331 "If you want to use this partition for swap space, select Swap.\n" 332 "If you want to put a filesystem on it, choose FS.", 333 -1, -1, 2, 2, fs_types, selection, NULL, NULL); 334 DialogX = DialogY = 0; 335 if (!i) { 336 if (!strcmp(selection, "FS")) 337 return PART_FILESYSTEM; 338 else if (!strcmp(selection, "Swap")) 339 return PART_SWAP; 340 } 341 return PART_NONE; 342} 343 344/* If the user wants a special newfs command for this, set it */ 345static void 346getNewfsCmd(PartInfo *p) 347{ 348 char *val; 349 350 val = msgGetInput(p->newfs_cmd, 351 "Please enter the newfs command and options you'd like to use in\n" 352 "creating this file system."); 353 if (val) 354 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 355} 356 357#define MAX_MOUNT_NAME 12 358 359#define PART_PART_COL 0 360#define PART_MOUNT_COL 8 361#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 362#define PART_NEWFS_COL (PART_SIZE_COL + 7) 363#define PART_OFF 38 364 365/* stick this all up on the screen */ 366static void 367print_label_chunks(void) 368{ 369 int i, j, srow, prow, pcol; 370 int sz; 371 372 attrset(A_REVERSE); 373 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 374 attrset(A_NORMAL); 375 376 for (i = 0; i < 2; i++) { 377 mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 378 mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 379 380 mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 381 mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 382 383 mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 384 mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 385 386 mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 387 mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 388 } 389 srow = CHUNK_SLICE_START_ROW; 390 prow = 0; 391 pcol = 0; 392 393 for (i = 0; label_chunk_info[i].c; i++) { 394 /* Is it a slice entry displayed at the top? */ 395 if (label_chunk_info[i].type == PART_SLICE) { 396 sz = space_free(label_chunk_info[i].c); 397 if (i == here) 398 attrset(ATTR_SELECTED); 399 mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 400 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, sz, (sz / ONE_MEG)); 401 attrset(A_NORMAL); 402 clrtoeol(); 403 move(0, 0); 404 refresh(); 405 } 406 /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 407 else { 408 char onestr[PART_OFF], num[10], *mountpoint, *newfs; 409 410 /* 411 * We copy this into a blank-padded string so that it looks like 412 * a solid bar in reverse-video 413 */ 414 memset(onestr, ' ', PART_OFF - 1); 415 onestr[PART_OFF - 1] = '\0'; 416 /* Go for two columns if we've written one full columns worth */ 417 if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) { 418 pcol = PART_OFF; 419 prow = 0; 420 } 421 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 422 /* If it's a filesystem, display the mountpoint */ 423 if (label_chunk_info[i].c->private_data 424 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 425 mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 426 else 427 mountpoint = "<none>"; 428 429 /* Now display the newfs field */ 430 if (label_chunk_info[i].type == PART_FAT) 431 newfs = "DOS"; 432 else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) 433 newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N"; 434 else if (label_chunk_info[i].type == PART_SWAP) 435 newfs = "SWAP"; 436 else 437 newfs = "*"; 438 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 439 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 440 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 441 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 442 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 443 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 444 if (i == here) 445 wattrset(ChunkWin, ATTR_SELECTED); 446 mvwaddstr(ChunkWin, prow, pcol, onestr); 447 wattrset(ChunkWin, A_NORMAL); 448 wrefresh(ChunkWin); 449 move(0, 0); 450 ++prow; 451 } 452 } 453} 454 455static void 456print_command_summary(void) 457{ 458 mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 459 mvprintw(18, 0, "C = Create D = Delete M = Mount"); 460 if (!RunningAsInit) 461 mvprintw(18, 47, "W = Write"); 462 mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish"); 463 mvprintw(20, 0, "A = Auto Defaults for all!"); 464 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 465 move(0, 0); 466} 467 468static void 469clear_wins(void) 470{ 471 clear(); 472 wclear(ChunkWin); 473} 474 475static int 476diskLabel(char *str) 477{ 478 int sz, key = 0; 479 Boolean labeling; 480 char *msg = NULL; 481 PartInfo *p, *oldp; 482 PartType type; 483 Device **devs; 484 485 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 486 if (!devs) { 487 msgConfirm("No disks found!"); 488 return DITEM_FAILURE; 489 } 490 491 labeling = TRUE; 492 keypad(stdscr, TRUE); 493 record_label_chunks(devs); 494 495 clear(); 496 while (labeling) { 497 print_label_chunks(); 498 print_command_summary(); 499 if (msg) { 500 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 501 clrtoeol(); 502 beep(); 503 msg = NULL; 504 } 505 else { 506 move(23, 0); 507 clrtoeol(); 508 } 509 refresh(); 510 key = getch(); 511 switch (toupper(key)) { 512 int i; 513 static char _msg[40]; 514 515 case '\014': /* ^L */ 516 clear_wins(); 517 break; 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 clear_wins(); 551 break; 552 553 case 'A': 554 if (label_chunk_info[here].type != PART_SLICE) { 555 msg = "You can only do this in a disk slice (at top of screen)"; 556 break; 557 } 558 sz = space_free(label_chunk_info[here].c); 559 if (sz <= FS_MIN_SIZE) 560 msg = "Not enough free space to create a new partition in the slice"; 561 else { 562 struct chunk *tmp; 563 int mib[2]; 564 int physmem; 565 size_t size, swsize; 566 char *cp; 567 Chunk *rootdev, *swapdev, *usrdev, *vardev; 568 569 (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev); 570 if (!rootdev) { 571 cp = variable_get(VAR_ROOT_SIZE); 572 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 573 (cp ? atoi(cp) : 32) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT); 574 if (!tmp) { 575 msgConfirm("Unable to create the root partition. Too big?"); 576 clear_wins(); 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 584 if (!swapdev) { 585 cp = variable_get(VAR_SWAP_SIZE); 586 if (cp) 587 swsize = atoi(cp) * ONE_MEG; 588 else { 589 mib[0] = CTL_HW; 590 mib[1] = HW_PHYSMEM; 591 size = sizeof physmem; 592 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 593 swsize = 16 * ONE_MEG + (physmem * 2 / 512); 594 } 595 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 596 swsize, part, FS_SWAP, 0); 597 if (!tmp) { 598 msgConfirm("Unable to create the swap partition. Too big?"); 599 clear_wins(); 600 break; 601 } 602 tmp->private_data = 0; 603 tmp->private_free = safe_free; 604 record_label_chunks(devs); 605 } 606 607 if (!vardev) { 608 cp = variable_get(VAR_VAR_SIZE); 609 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 610 (cp ? atoi(cp) : VAR_MIN_SIZE) * ONE_MEG, part, FS_BSDFFS, 0); 611 if (!tmp) { 612 msgConfirm("Less than %dMB free for /var - you will need to\n" 613 "partition your disk manually with a custom install!", 614 (cp ? atoi(cp) : VAR_MIN_SIZE)); 615 clear_wins(); 616 break; 617 } 618 tmp->private_data = new_part("/var", TRUE, tmp->size); 619 tmp->private_free = safe_free; 620 record_label_chunks(devs); 621 } 622 623 if (!usrdev) { 624 cp = variable_get(VAR_USR_SIZE); 625 if (cp) 626 sz = atoi(cp) * ONE_MEG; 627 else 628 sz = space_free(label_chunk_info[here].c); 629 if (!sz || sz < (USR_MIN_SIZE * ONE_MEG)) { 630 msgConfirm("Less than %dMB free for /usr - you will need to\n" 631 "partition your disk manually with a custom install!", USR_MIN_SIZE); 632 clear_wins(); 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 clear_wins(); 643 break; 644 } 645 tmp->private_data = new_part("/usr", TRUE, tmp->size); 646 tmp->private_free = safe_free; 647 record_label_chunks(devs); 648 } 649 /* At this point, we're reasonably "labelled" */ 650 variable_set2(DISK_LABELLED, "yes"); 651 } 652 break; 653 654 case 'C': 655 if (label_chunk_info[here].type != PART_SLICE) { 656 msg = "You can only do this in a master partition (see top of screen)"; 657 break; 658 } 659 sz = space_free(label_chunk_info[here].c); 660 if (sz <= FS_MIN_SIZE) { 661 msg = "Not enough space to create an additional FreeBSD partition"; 662 break; 663 } 664 else { 665 char *val, *cp; 666 int size; 667 struct chunk *tmp; 668 char osize[80]; 669 u_long flags = 0; 670 671 sprintf(osize, "%d", sz); 672 DialogX = 3; 673 DialogY = 1; 674 val = msgGetInput(osize, 675 "Please specify the partition size in blocks or append a trailing M for\n" 676 "megabytes or C for cylinders. %d blocks (%dMB) are free.", 677 sz, sz / ONE_MEG); 678 DialogX = DialogY = 0; 679 if (!val || (size = strtol(val, &cp, 0)) <= 0) { 680 clear_wins(); 681 break; 682 } 683 684 if (*cp) { 685 if (toupper(*cp) == 'M') 686 size *= ONE_MEG; 687 else if (toupper(*cp) == 'C') 688 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 689 } 690 if (size <= FS_MIN_SIZE) { 691 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 692 clear_wins(); 693 break; 694 } 695 type = get_partition_type(); 696 if (type == PART_NONE) { 697 clear_wins(); 698 beep(); 699 break; 700 } 701 702 if (type == PART_FILESYSTEM) { 703 if ((p = get_mountpoint(NULL)) == NULL) { 704 clear_wins(); 705 beep(); 706 break; 707 } 708 else if (!strcmp(p->mountpoint, "/")) 709 flags |= CHUNK_IS_ROOT; 710 else 711 flags &= ~CHUNK_IS_ROOT; 712 } 713 else 714 p = NULL; 715 716 if ((flags & CHUNK_IS_ROOT)) { 717 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 718 msgConfirm("This region cannot be used for your root partition as the\n" 719 "FreeBSD boot code cannot deal with a root partition created\n" 720 "in that location. Please choose another location or smaller\n" 721 "size for your root partition and try again!"); 722 clear_wins(); 723 break; 724 } 725 if (size < (ROOT_MIN_SIZE * ONE_MEG)) { 726 msgConfirm("Warning: This is smaller than the recommended size for a\n" 727 "root partition. For a variety of reasons, root\n" 728 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 729 } 730 } 731 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 732 label_chunk_info[here].c, 733 size, part, 734 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 735 flags); 736 if (!tmp) { 737 msgConfirm("Unable to create the partition. Too big?"); 738 clear_wins(); 739 break; 740 } 741 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 742 msgConfirm("This region cannot be used for your root partition as it starts\n" 743 "or extends past the 1024'th cylinder mark and is thus a\n" 744 "poor location to boot from. Please choose another\n" 745 "location (or smaller size) for your root partition and try again!"); 746 Delete_Chunk(label_chunk_info[here].c->disk, tmp); 747 clear_wins(); 748 break; 749 } 750 if (type != PART_SWAP) { 751 /* This is needed to tell the newfs -u about the size */ 752 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 753 safe_free(p); 754 } 755 else 756 tmp->private_data = p; 757 tmp->private_free = safe_free; 758 variable_set2(DISK_LABELLED, "yes"); 759 record_label_chunks(devs); 760 clear_wins(); 761 } 762 break; 763 764 case KEY_DC: 765 case 'D': /* delete */ 766 if (label_chunk_info[here].type == PART_SLICE) { 767 msg = MSG_NOT_APPLICABLE; 768 break; 769 } 770 else if (label_chunk_info[here].type == PART_FAT) { 771 msg = "Use the Disk Partition Editor to delete DOS partitions"; 772 break; 773 } 774 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 775 variable_set2(DISK_LABELLED, "yes"); 776 record_label_chunks(devs); 777 break; 778 779 case 'M': /* mount */ 780 switch(label_chunk_info[here].type) { 781 case PART_SLICE: 782 msg = MSG_NOT_APPLICABLE; 783 break; 784 785 case PART_SWAP: 786 msg = "You don't need to specify a mountpoint for a swap partition."; 787 break; 788 789 case PART_FAT: 790 case PART_FILESYSTEM: 791 oldp = label_chunk_info[here].c->private_data; 792 p = get_mountpoint(label_chunk_info[here].c); 793 if (p) { 794 if (!oldp) 795 p->newfs = FALSE; 796 if (label_chunk_info[here].type == PART_FAT 797 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 798 || !strcmp(p->mountpoint, "/var"))) { 799 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 800 strcpy(p->mountpoint, "/bogus"); 801 } 802 } 803 variable_set2(DISK_LABELLED, "yes"); 804 record_label_chunks(devs); 805 clear(); 806 break; 807 808 default: 809 msgFatal("Bogus partition under cursor???"); 810 break; 811 } 812 break; 813 814 case 'N': /* Set newfs options */ 815 if (label_chunk_info[here].c->private_data && 816 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 817 getNewfsCmd(label_chunk_info[here].c->private_data); 818 else 819 msg = MSG_NOT_APPLICABLE; 820 break; 821 822 case 'T': /* Toggle newfs state */ 823 if (label_chunk_info[here].type == PART_FILESYSTEM) { 824 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 825 label_chunk_info[here].c->private_data = 826 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 827 safe_free(pi); 828 label_chunk_info[here].c->private_free = safe_free; 829 variable_set2(DISK_LABELLED, "yes"); 830 } 831 else 832 msg = MSG_NOT_APPLICABLE; 833 break; 834 835 case 'U': 836 clear(); 837 if (msgYesNo("Are you SURE you want to Undo everything?")) 838 break; 839 variable_unset(DISK_PARTITIONED); 840 variable_unset(DISK_LABELLED); 841 for (i = 0; devs[i]; i++) { 842 Disk *d; 843 844 if (!devs[i]->enabled) 845 continue; 846 else if ((d = Open_Disk(devs[i]->name)) != NULL) { 847 Free_Disk(devs[i]->private); 848 devs[i]->private = d; 849 diskPartition(devs[i], d); 850 } 851 } 852 record_label_chunks(devs); 853 clear(); 854 break; 855 856 case 'W': 857 if (!msgYesNo("You also have the option of doing this later in one final 'commit'\n" 858 "operation, and it should also be noted that this option is NOT for\n" 859 "use during new installations but rather for modifying existing ones.\n\n" 860 "Are you absolutely SURE you want to do this now?")) { 861 variable_set2(DISK_LABELLED, "yes"); 862 diskLabelCommit(NULL); 863 } 864 clear(); 865 break; 866 867 case '|': 868 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 869 "This is an entirely undocumented feature which you are not\n" 870 "expected to understand!")) { 871 int i; 872 Device **devs; 873 874 dialog_clear(); 875 end_dialog(); 876 DialogActive = FALSE; 877 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 878 if (!devs) { 879 msgConfirm("Can't find any disk devices!"); 880 break; 881 } 882 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 883 if (devs[i]->enabled) 884 slice_wizard(((Disk *)devs[i]->private)); 885 } 886 variable_set2(DISK_LABELLED, "yes"); 887 DialogActive = TRUE; 888 record_label_chunks(devs); 889 clear(); 890 } 891 else 892 msg = "A most prudent choice!"; 893 break; 894 895 case 'Q': 896 labeling = FALSE; 897 break; 898 899 default: 900 beep(); 901 sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 902 msg = _msg; 903 break; 904 } 905 } 906 return DITEM_SUCCESS | DITEM_RESTORE; 907} 908