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