label.c revision 15440
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.45 1996/04/28 03:27:08 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 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(A_REVERSE); 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, A_REVERSE); 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, 48, "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, "The default target will be displayed in "); 468 469 attrset(A_REVERSE); 470 addstr("reverse"); 471 attrset(A_NORMAL); 472 addstr(" video."); 473 mvprintw(23, 0, "Use F1 or ? to get more help, arrow keys to move."); 474 move(0, 0); 475} 476 477static int 478diskLabel(char *str) 479{ 480 int sz, key = 0, first_time = 1; 481 Boolean labeling; 482 char *msg = NULL; 483 PartInfo *p, *oldp; 484 PartType type; 485 Device **devs; 486 WINDOW *w; 487 488 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 489 if (!devs) { 490 msgConfirm("No disks found!"); 491 return DITEM_FAILURE; 492 } 493 494 labeling = TRUE; 495 keypad(stdscr, TRUE); 496 record_label_chunks(devs); 497 498 w = savescr(); 499 dialog_clear(); clear(); 500 while (labeling) { 501 print_label_chunks(); 502 if (first_time) { 503 print_command_summary(); 504 first_time = 0; 505 } 506 if (msg) { 507 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 508 clrtoeol(); 509 beep(); 510 msg = NULL; 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 variable_set2(DISK_LABELLED, "yes"); 835 diskLabelCommit(NULL); 836 } 837 break; 838 839 case '|': 840 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 841 "This is an entirely undocumented feature which you are not\n" 842 "expected to understand!")) { 843 int i; 844 Device **devs; 845 WINDOW *save = savescr(); 846 847 dialog_clear(); 848 end_dialog(); 849 DialogActive = FALSE; 850 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 851 if (!devs) { 852 msgConfirm("Can't find any disk devices!"); 853 break; 854 } 855 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 856 if (devs[i]->enabled) 857 slice_wizard(((Disk *)devs[i]->private)); 858 } 859 variable_set2(DISK_LABELLED, "yes"); 860 DialogActive = TRUE; 861 dialog_clear(); 862 restorescr(save); 863 record_label_chunks(devs); 864 } 865 else 866 msg = "A most prudent choice!"; 867 break; 868 869 case 'Q': 870 labeling = FALSE; 871 break; 872 873 default: 874 beep(); 875 msg = "Type F1 or ? for help"; 876 break; 877 } 878 } 879 restorescr(w); 880 return DITEM_SUCCESS; 881} 882