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