label.c revision 10882
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.32.2.2 1995/07/21 11:45:39 rgrimes 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 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by Jordan Hubbard 25 * for the FreeBSD Project. 26 * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 27 * endorse or promote products derived from this software without specific 28 * prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 */ 43 44#include "sysinstall.h" 45#include <ctype.h> 46#include <sys/disklabel.h> 47#include <sys/param.h> 48#undef TRUE 49#undef FALSE 50#include <sys/sysctl.h> 51 52/* 53 * Everything to do with editing the contents of disk labels. 54 */ 55 56/* A nice message we use a lot in the disklabel editor */ 57#define MSG_NOT_APPLICABLE "That option is not applicable here" 58 59/* Where to start printing the freebsd slices */ 60#define CHUNK_SLICE_START_ROW 2 61#define CHUNK_PART_START_ROW 11 62 63/* One MB worth of blocks */ 64#define ONE_MEG 2048 65 66/* The smallest filesystem we're willing to create */ 67#define FS_MIN_SIZE ONE_MEG 68 69/* The smallest root filesystem we're willing to create */ 70#define ROOT_MIN_SIZE (20 * ONE_MEG) 71 72/* All the chunks currently displayed on the screen */ 73static struct { 74 struct chunk *c; 75 PartType type; 76} label_chunk_info[MAX_CHUNKS + 1]; 77static int here; 78 79/* See if we're already using a desired partition name */ 80static Boolean 81check_conflict(char *name) 82{ 83 int i; 84 85 for (i = 0; label_chunk_info[i].c; i++) 86 if (label_chunk_info[i].type == PART_FILESYSTEM && label_chunk_info[i].c->private 87 && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name)) 88 return TRUE; 89 return FALSE; 90} 91 92/* How much space is in this FreeBSD slice? */ 93static int 94space_free(struct chunk *c) 95{ 96 struct chunk *c1 = c->part; 97 int sz = c->size; 98 99 while (c1) { 100 if (c1->type != unused) 101 sz -= c1->size; 102 c1 = c1->next; 103 } 104 if (sz < 0) 105 msgFatal("Partitions are larger than actual chunk??"); 106 return sz; 107} 108 109/* Snapshot the current situation into the displayed chunks structure */ 110static void 111record_label_chunks() 112{ 113 int i, j, p; 114 struct chunk *c1, *c2; 115 Device **devs; 116 Disk *d; 117 118 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 119 if (!devs) { 120 msgConfirm("No disks found!"); 121 return; 122 } 123 124 j = p = 0; 125 /* First buzz through and pick up the FreeBSD slices */ 126 for (i = 0; devs[i]; i++) { 127 if (!devs[i]->enabled) 128 continue; 129 d = (Disk *)devs[i]->private; 130 if (!d->chunks) 131 msgFatal("No chunk list found for %s!", d->name); 132 133 /* Put the slice entries first */ 134 for (c1 = d->chunks->part; c1; c1 = c1->next) { 135 if (c1->type == freebsd) { 136 label_chunk_info[j].type = PART_SLICE; 137 label_chunk_info[j].c = c1; 138 ++j; 139 } 140 } 141 } 142 /* Now run through again and get the FreeBSD partition entries */ 143 for (i = 0; devs[i]; i++) { 144 if (!devs[i]->enabled) 145 continue; 146 d = (Disk *)devs[i]->private; 147 /* Then buzz through and pick up the partitions */ 148 for (c1 = d->chunks->part; c1; c1 = c1->next) { 149 if (c1->type == freebsd) { 150 for (c2 = c1->part; c2; c2 = c2->next) { 151 if (c2->type == part) { 152 if (c2->subtype == FS_SWAP) 153 label_chunk_info[j].type = PART_SWAP; 154 else 155 label_chunk_info[j].type = PART_FILESYSTEM; 156 label_chunk_info[j].c = c2; 157 ++j; 158 } 159 } 160 } 161 else if (c1->type == fat) { 162 label_chunk_info[j].type = PART_FAT; 163 label_chunk_info[j].c = c1; 164 ++j; 165 } 166 } 167 } 168 label_chunk_info[j].c = NULL; 169 if (here >= j) 170 here = j ? j - 1 : 0; 171} 172 173/* A new partition entry */ 174static PartInfo * 175new_part(char *mpoint, Boolean newfs, u_long size) 176{ 177 PartInfo *ret; 178 u_long target, divisor; 179 180 if (!mpoint) 181 mpoint = "/change_me"; 182 183 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 184 strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 185 strcpy(ret->newfs_cmd, "newfs -b 8192 -f 2048"); 186 ret->newfs = newfs; 187 if (!size) 188 return ret; 189 for (target = size; target; target--) { 190 for (divisor = 4096 ; divisor > 1023; divisor--) { 191 if (!(target % divisor)) { 192 sprintf(ret->newfs_cmd + strlen(ret->newfs_cmd), " -u %ld",divisor); 193 return ret; 194 } 195 } 196 } 197 return ret; 198} 199 200/* Get the mountpoint for a partition and save it away */ 201PartInfo * 202get_mountpoint(struct chunk *old) 203{ 204 char *val; 205 PartInfo *tmp; 206 207 if (old && old->private) 208 tmp = old->private; 209 else 210 tmp = NULL; 211 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 212 if (!val || !*val) { 213 if (!old) 214 return NULL; 215 else { 216 free(old->private); 217 old->private = NULL; 218 } 219 return NULL; 220 } 221 222 /* Is it just the same value? */ 223 if (tmp && !strcmp(tmp->mountpoint, val)) 224 return NULL; 225 226 /* Did we use it already? */ 227 if (check_conflict(val)) { 228 msgConfirm("You already have a mount point for %s assigned!", val); 229 return NULL; 230 } 231 232 /* Is it bogus? */ 233 if (*val != '/') { 234 msgConfirm("Mount point must start with a / character"); 235 return NULL; 236 } 237 238 /* Is it going to be mounted on root? */ 239 if (!strcmp(val, "/")) { 240 if (old) 241 old->flags |= CHUNK_IS_ROOT; 242 } 243 else if (old) 244 old->flags &= ~CHUNK_IS_ROOT; 245 246 safe_free(tmp); 247 tmp = new_part(val, TRUE, 0); 248 if (old) { 249 old->private = tmp; 250 old->private_free = safe_free; 251 } 252 return tmp; 253} 254 255/* Get the type of the new partiton */ 256static PartType 257get_partition_type(void) 258{ 259 char selection[20]; 260 int i; 261 262 static unsigned char *fs_types[] = { 263 "FS", 264 "A file system", 265 "Swap", 266 "A swap partition.", 267 }; 268 i = dialog_menu("Please choose a partition type", 269 "If you want to use this partition for swap space, select Swap.\nIf you want to put a filesystem on it, choose FS.", -1, -1, 2, 2, fs_types, selection, NULL, NULL); 270 if (!i) { 271 if (!strcmp(selection, "FS")) 272 return PART_FILESYSTEM; 273 else if (!strcmp(selection, "Swap")) 274 return PART_SWAP; 275 } 276 return PART_NONE; 277} 278 279/* If the user wants a special newfs command for this, set it */ 280static void 281getNewfsCmd(PartInfo *p) 282{ 283 char *val; 284 285 val = msgGetInput(p->newfs_cmd, 286 "Please enter the newfs command and options you'd like to use in\ncreating this file system."); 287 if (val) 288 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 289} 290 291 292#define MAX_MOUNT_NAME 12 293 294#define PART_PART_COL 0 295#define PART_MOUNT_COL 8 296#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 297#define PART_NEWFS_COL (PART_SIZE_COL + 7) 298#define PART_OFF 38 299 300/* How many mounted partitions to display in column before going to next */ 301#define CHUNK_COLUMN_MAX 5 302 303/* stick this all up on the screen */ 304static void 305print_label_chunks(void) 306{ 307 int i, j, srow, prow, pcol; 308 int sz; 309 310 attrset(A_REVERSE); 311 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 312 clrtobot(); 313 attrset(A_NORMAL); 314 315 for (i = 0; i < 2; i++) { 316 mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part"); 317 mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----"); 318 319 mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 320 mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 321 322 mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 323 mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 324 325 mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 326 mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 327 } 328 srow = CHUNK_SLICE_START_ROW; 329 prow = CHUNK_PART_START_ROW; 330 pcol = 0; 331 332 for (i = 0; label_chunk_info[i].c; i++) { 333 if (i == here) 334 attrset(A_REVERSE); 335 /* Is it a slice entry displayed at the top? */ 336 if (label_chunk_info[i].type == PART_SLICE) { 337 sz = space_free(label_chunk_info[i].c); 338 mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 339 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, sz, (sz / ONE_MEG)); 340 } 341 /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */ 342 else { 343 char onestr[PART_OFF], num[10], *mountpoint, *newfs; 344 345 /* 346 * We copy this into a blank-padded string so that it looks like 347 * a solid bar in reverse-video 348 */ 349 memset(onestr, ' ', PART_OFF - 1); 350 onestr[PART_OFF - 1] = '\0'; 351 /* Go for two columns */ 352 if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) { 353 pcol = PART_OFF; 354 prow = CHUNK_PART_START_ROW; 355 } 356 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 357 /* If it's a filesystem, display the mountpoint */ 358 if (label_chunk_info[i].c->private 359 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 360 mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint; 361 else 362 mountpoint = "<none>"; 363 364 /* Now display the newfs field */ 365 if (label_chunk_info[i].type == PART_FAT) 366 newfs = "DOS"; 367 else if (label_chunk_info[i].c->private && label_chunk_info[i].type == PART_FILESYSTEM) 368 newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "UFS Y" : "UFS N"; 369 else if (label_chunk_info[i].type == PART_SWAP) 370 newfs = "SWAP"; 371 else 372 newfs = "*"; 373 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 374 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 375 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 376 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 377 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 378 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 379 mvaddstr(prow, pcol, onestr); 380 ++prow; 381 } 382 if (i == here) 383 attrset(A_NORMAL); 384 } 385} 386 387static void 388print_command_summary() 389{ 390 mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 391 mvprintw(18, 0, "C = Create D = Delete M = Mount W = Write"); 392 mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish"); 393 mvprintw(20, 0, "A = Auto Defaults for all!"); 394 mvprintw(22, 0, "The default target will be displayed in "); 395 396 attrset(A_REVERSE); 397 addstr("reverse"); 398 attrset(A_NORMAL); 399 addstr(" video."); 400 mvprintw(23, 0, "Use F1 or ? to get more help, arrow keys to move."); 401 move(0, 0); 402} 403 404int 405diskLabelEditor(char *str) 406{ 407 int sz, key = 0; 408 Boolean labeling; 409 char *msg = NULL; 410 PartInfo *p, *oldp; 411 PartType type; 412 Device **devs; 413 414 labeling = TRUE; 415 keypad(stdscr, TRUE); 416 record_label_chunks(); 417 418 if (!getenv(DISK_PARTITIONED)) { 419 msgConfirm("You need to partition your disk(s) before you can assign disk labels."); 420 return 0; 421 } 422 dialog_clear(); clear(); 423 while (labeling) { 424 clear(); 425 print_label_chunks(); 426 print_command_summary(); 427 if (msg) { 428 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 429 beep(); 430 msg = NULL; 431 } 432 refresh(); 433 key = toupper(getch()); 434 switch (key) { 435 int i, cnt; 436 437 case '\014': /* ^L */ 438 continue; 439 440 case KEY_UP: 441 case '-': 442 if (here != 0) 443 --here; 444 else 445 while (label_chunk_info[here + 1].c) 446 ++here; 447 break; 448 449 case KEY_DOWN: 450 case '+': 451 case '\r': 452 case '\n': 453 if (label_chunk_info[here + 1].c) 454 ++here; 455 else 456 here = 0; 457 break; 458 459 case KEY_HOME: 460 here = 0; 461 break; 462 463 case KEY_END: 464 while (label_chunk_info[here + 1].c) 465 ++here; 466 break; 467 468 case KEY_F(1): 469 case '?': 470 systemDisplayFile("partition.hlp"); 471 break; 472 473 case 'A': 474 if (label_chunk_info[here].type != PART_SLICE) { 475 msg = "You can only do this in a master partition (see top of screen)"; 476 break; 477 } 478 479 cnt = i = 0; 480 while (label_chunk_info[i].c) 481 if (label_chunk_info[i++].type != PART_SLICE) 482 cnt++; 483 if (cnt == (CHUNK_COLUMN_MAX * 2) + 4) { 484 msgConfirm("Sorry, I can't fit any more partitions on the screen! You can get around\nthis limitation by partitioning your disks individually rather than all\nat once. This will be fixed just as soon as we get a scrolling partition\nbox written. Sorry for the inconvenience!"); 485 break; 486 } 487 488 sz = space_free(label_chunk_info[here].c); 489 if (sz <= FS_MIN_SIZE) { 490 msg = "Not enough space to create additional FreeBSD partition"; 491 break; 492 } 493 { 494 struct chunk *tmp; 495 int mib[2]; 496 int physmem; 497 size_t size; 498 499 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 500 label_chunk_info[here].c, 501 32 * ONE_MEG, part, FS_BSDFFS, 502 CHUNK_IS_ROOT); 503 504 if (!tmp) { 505 msgConfirm("Unable to create the root partition. Too big?"); 506 break; 507 } 508 tmp->private = new_part("/", TRUE, tmp->size); 509 tmp->private_free = safe_free; 510 record_label_chunks(); 511 512 mib[0] = CTL_HW; 513 mib[1] = HW_PHYSMEM; 514 size = sizeof physmem; 515 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 516 517 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 518 label_chunk_info[here].c, 519 physmem * 2 / 512, part, FS_SWAP, 0); 520 if (!tmp) { 521 msgConfirm("Unable to create the swap partition. Too big?"); 522 break; 523 } 524 525 tmp->private = 0; 526 tmp->private_free = safe_free; 527 record_label_chunks(); 528 529 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 530 label_chunk_info[here].c, 531 16 * ONE_MEG, part, FS_BSDFFS, 0); 532 if (!tmp) { 533 msgConfirm("Unable to create the /var partition. Too big?"); 534 break; 535 } 536 tmp->private = new_part("/var", TRUE, tmp->size); 537 tmp->private_free = safe_free; 538 record_label_chunks(); 539 540 sz = space_free(label_chunk_info[here].c); 541 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 542 label_chunk_info[here].c, 543 sz, part, FS_BSDFFS, 0); 544 if (!tmp) { 545 msgConfirm("Unable to create the /usr partition. Too big?"); 546 break; 547 } 548 tmp->private = new_part("/usr", TRUE, tmp->size); 549 tmp->private_free = safe_free; 550 record_label_chunks(); 551 } 552 break; 553 554 case 'C': 555 if (label_chunk_info[here].type != PART_SLICE) { 556 msg = "You can only do this in a master partition (see top of screen)"; 557 break; 558 } 559 else { 560 int i, cnt; 561 562 cnt = i = 0; 563 while (label_chunk_info[i].c) 564 if (label_chunk_info[i++].type != PART_SLICE) 565 cnt++; 566 if (cnt == (CHUNK_COLUMN_MAX * 2)) { 567 msgConfirm("Sorry, I can't fit any more partitions on the screen! You can get around\nthis limitation by partitioning your disks individually rather than all\nat once. This will be fixed just as soon as we get a scrolling partition\nbox written. Sorry for the inconvenience!"); 568 break; 569 } 570 } 571 sz = space_free(label_chunk_info[here].c); 572 if (sz <= FS_MIN_SIZE) { 573 msg = "Not enough space to create additional FreeBSD partition"; 574 break; 575 } 576 { 577 char *val, *cp; 578 int size; 579 struct chunk *tmp; 580 char osize[80]; 581 u_long flags = 0; 582 583 sprintf(osize, "%d", sz); 584 val = msgGetInput(osize, "Please specify the size for new FreeBSD partition in blocks, or\nappend a trailing `M' for megabytes (e.g. 20M) or `C' for cylinders.\n\nSpace free is %d blocks (%dMB)", sz, sz / ONE_MEG); 585 if (!val || (size = strtol(val, &cp, 0)) <= 0) 586 break; 587 588 if (*cp) { 589 if (toupper(*cp) == 'M') 590 size *= ONE_MEG; 591 else if (toupper(*cp) == 'C') 592 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 593 } 594 if (size <= FS_MIN_SIZE) { 595 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 596 break; 597 } 598 type = get_partition_type(); 599 if (type == PART_NONE) 600 break; 601 602 if (type == PART_FILESYSTEM) { 603 if ((p = get_mountpoint(NULL)) == NULL) 604 break; 605 else if (!strcmp(p->mountpoint, "/")) 606 flags |= CHUNK_IS_ROOT; 607 else 608 flags &= ~CHUNK_IS_ROOT; 609 } else 610 p = NULL; 611 612 if ((flags & CHUNK_IS_ROOT)) { 613 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 614 msgConfirm("This region cannot be used for your root partition as\nthe FreeBSD boot code cannot deal with a root partition created in\nsuch a location. Please choose another location for your root\npartition and try again!"); 615 break; 616 } 617 if (size < ROOT_MIN_SIZE) 618 msgConfirm("Warning: This is smaller than the recommended size for a\nroot partition. For a variety of reasons, root\npartitions should usually be at least %dMB in size", ROOT_MIN_SIZE / ONE_MEG); 619 } 620 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 621 label_chunk_info[here].c, 622 size, part, 623 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 624 flags); 625 if (!tmp) { 626 msgConfirm("Unable to create the partition. Too big?"); 627 break; 628 } 629 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 630 msgConfirm("This region cannot be used for your root partition as it starts\nor extends past the 1024'th cylinder mark and is thus a\npoor location to boot from. Please choose another\nlocation for your root partition and try again!"); 631 Delete_Chunk(label_chunk_info[here].c->disk, tmp); 632 break; 633 } 634 if (type != PART_SWAP) { 635 /* This is needed to tell the newfs -u about the size */ 636 tmp->private = new_part(p->mountpoint, p->newfs, tmp->size); 637 tmp->private_free = safe_free; 638 safe_free(p); 639 } else { 640 tmp->private = p; 641 } 642 tmp->private_free = safe_free; 643 record_label_chunks(); 644 } 645 break; 646 647 case 'D': /* delete */ 648 if (label_chunk_info[here].type == PART_SLICE) { 649 msg = MSG_NOT_APPLICABLE; 650 break; 651 } 652 else if (label_chunk_info[here].type == PART_FAT) { 653 msg = "Use the Disk Partition Editor to delete DOS partitions"; 654 break; 655 } 656 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 657 record_label_chunks(); 658 break; 659 660 case 'M': /* mount */ 661 switch(label_chunk_info[here].type) { 662 case PART_SLICE: 663 msg = MSG_NOT_APPLICABLE; 664 break; 665 666 case PART_SWAP: 667 msg = "You don't need to specify a mountpoint for a swap partition."; 668 break; 669 670 case PART_FAT: 671 case PART_FILESYSTEM: 672 oldp = label_chunk_info[here].c->private; 673 p = get_mountpoint(label_chunk_info[here].c); 674 if (p) { 675 if (!oldp) 676 p->newfs = FALSE; 677 if (label_chunk_info[here].type == PART_FAT 678 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 679 || !strcmp(p->mountpoint, "/var"))) { 680 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 681 strcpy(p->mountpoint, "/bogus"); 682 } 683 } 684 record_label_chunks(); 685 break; 686 687 default: 688 msgFatal("Bogus partition under cursor???"); 689 break; 690 } 691 break; 692 693 case 'N': /* Set newfs options */ 694 if (label_chunk_info[here].c->private && 695 ((PartInfo *)label_chunk_info[here].c->private)->newfs) 696 getNewfsCmd(label_chunk_info[here].c->private); 697 else 698 msg = MSG_NOT_APPLICABLE; 699 break; 700 701 case 'T': /* Toggle newfs state */ 702 if (label_chunk_info[here].type == PART_FILESYSTEM) { 703 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private); 704 label_chunk_info[here].c->private = new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 705 safe_free(pi); 706 label_chunk_info[here].c->private_free = safe_free; 707 } 708 else 709 msg = MSG_NOT_APPLICABLE; 710 break; 711 712 case 'U': 713 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 714 for (i = 0; devs[i]; i++) { 715 if (!devs[i]->enabled) 716 continue; 717 else { 718 char *cp = devs[i]->name; 719 720 Free_Disk(devs[i]->private); 721 devs[i]->private = Open_Disk(cp); 722 } 723 } 724 record_label_chunks(); 725 break; 726 727 case 'W': 728 if (!msgYesNo("Are you sure that you wish to make and mount all filesystems\nat this time? You also have the option of doing it later in\none final 'commit' operation, and if you're at all unsure as\nto which option to chose, then chose No.")) 729 diskLabelCommit(NULL); 730 break; 731 732 case '|': 733 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\nThis is an entirely undocumented feature which you are not\nexpected to understand!")) { 734 int i; 735 Device **devs; 736 737 dialog_clear(); 738 end_dialog(); 739 DialogActive = FALSE; 740 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 741 if (!devs) { 742 msgConfirm("Can't find any disk devicse!"); 743 break; 744 } 745 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 746 if (devs[i]->enabled) 747 slice_wizard(((Disk *)devs[i]->private)); 748 } 749 DialogActive = TRUE; 750 dialog_clear(); 751 record_label_chunks(); 752 } 753 else 754 msg = "A most prudent choice!"; 755 break; 756 757 case 'Q': 758 labeling = FALSE; 759 break; 760 761 default: 762 beep(); 763 msg = "Type F1 or ? for help"; 764 break; 765 } 766 } 767 variable_set2(DISK_LABELLED, "yes"); 768 dialog_clear(); 769 return 0; 770} 771 772int 773diskLabelCommit(char *str) 774{ 775 if (!getenv(DISK_LABELLED)) 776 msgConfirm("You must assign disk labels before this option can be used."); 777 else if (!installFilesystems()) 778 msgConfirm("Failed to make/mount all filesystems. Please correct\nwhatever went wrong and try again."); 779 return 0; 780} 781