label.c revision 97667
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 * $FreeBSD: head/usr.sbin/sade/label.c 97667 2002-05-31 13:38:17Z jhb $ 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#define AUTO_HOME 0 /* do not create /home automatically */ 44 45/* 46 * Everything to do with editing the contents of disk labels. 47 */ 48 49/* A nice message we use a lot in the disklabel editor */ 50#define MSG_NOT_APPLICABLE "That option is not applicable here" 51 52/* Where to start printing the freebsd slices */ 53#define CHUNK_SLICE_START_ROW 2 54#define CHUNK_PART_START_ROW 11 55 56/* The smallest filesystem we're willing to create */ 57#define FS_MIN_SIZE ONE_MEG 58 59/* 60 * Minimum partition sizes 61 */ 62#ifdef __alpha__ 63#define ROOT_MIN_SIZE 40 64#else 65#define ROOT_MIN_SIZE 30 66#endif 67#define SWAP_MIN_SIZE 32 68#define USR_MIN_SIZE 80 69#define VAR_MIN_SIZE 20 70#define TMP_MIN_SIZE 20 71#define HOME_MIN_SIZE 20 72 73/* 74 * Swap size limit for auto-partitioning (4G). 75 */ 76#define SWAP_AUTO_LIMIT_SIZE 4096 77 78/* 79 * Default partition sizes. If we do not have sufficient disk space 80 * for this configuration we scale things relative to the NOM vs DEFAULT 81 * sizes. If the disk is larger then /home will get any remaining space. 82 */ 83#define ROOT_DEFAULT_SIZE 128 84#define USR_DEFAULT_SIZE 3072 85#define VAR_DEFAULT_SIZE 256 86#define TMP_DEFAULT_SIZE 256 87#define HOME_DEFAULT_SIZE USR_DEFAULT_SIZE 88 89/* 90 * Nominal partition sizes. These are used to scale the default sizes down 91 * when we have insufficient disk space. If this isn't sufficient we scale 92 * down using the MIN sizes instead. 93 */ 94#define ROOT_NOMINAL_SIZE 128 95#define USR_NOMINAL_SIZE 512 96#define VAR_NOMINAL_SIZE 64 97#define TMP_NOMINAL_SIZE 64 98#define HOME_NOMINAL_SIZE USR_NOMINAL_SIZE 99 100/* The bottom-most row we're allowed to scribble on */ 101#define CHUNK_ROW_MAX 16 102 103 104/* All the chunks currently displayed on the screen */ 105static struct { 106 struct chunk *c; 107 PartType type; 108} label_chunk_info[MAX_CHUNKS + 1]; 109static int here; 110 111/*** with this value we try to track the most recently added label ***/ 112static int label_focus = 0, pslice_focus = 0; 113 114static int diskLabel(Device *dev); 115static int diskLabelNonInteractive(Device *dev); 116static char *try_auto_label(Device **devs, Device *dev, int perc, int *req); 117 118static int 119labelHook(dialogMenuItem *selected) 120{ 121 Device **devs = NULL; 122 123 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 124 if (!devs) { 125 msgConfirm("Unable to find disk %s!", selected->prompt); 126 return DITEM_FAILURE; 127 } 128 /* Toggle enabled status? */ 129 if (!devs[0]->enabled) { 130 devs[0]->enabled = TRUE; 131 diskLabel(devs[0]); 132 } 133 else 134 devs[0]->enabled = FALSE; 135 return DITEM_SUCCESS; 136} 137 138static int 139labelCheck(dialogMenuItem *selected) 140{ 141 Device **devs = NULL; 142 143 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 144 if (!devs || devs[0]->enabled == FALSE) 145 return FALSE; 146 return TRUE; 147} 148 149int 150diskLabelEditor(dialogMenuItem *self) 151{ 152 DMenu *menu; 153 Device **devs; 154 int i, cnt; 155 156 i = 0; 157 cnt = diskGetSelectCount(&devs); 158 if (cnt == -1) { 159 msgConfirm("No disks found! Please verify that your disk controller is being\n" 160 "properly probed at boot time. See the Hardware Guide on the\n" 161 "Documentation menu for clues on diagnosing this type of problem."); 162 return DITEM_FAILURE; 163 } 164 else if (cnt) { 165 /* Some are already selected */ 166 if (variable_get(VAR_NONINTERACTIVE) && 167 !variable_get(VAR_DISKINTERACTIVE)) 168 i = diskLabelNonInteractive(NULL); 169 else 170 i = diskLabel(NULL); 171 } 172 else { 173 /* No disks are selected, fall-back case now */ 174 cnt = deviceCount(devs); 175 if (cnt == 1) { 176 devs[0]->enabled = TRUE; 177 if (variable_get(VAR_NONINTERACTIVE) && 178 !variable_get(VAR_DISKINTERACTIVE)) 179 i = diskLabelNonInteractive(devs[0]); 180 else 181 i = diskLabel(devs[0]); 182 } 183 else { 184 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); 185 if (!menu) { 186 msgConfirm("No devices suitable for installation found!\n\n" 187 "Please verify that your disk controller (and attached drives)\n" 188 "were detected properly. This can be done by pressing the\n" 189 "[Scroll Lock] key and using the Arrow keys to move back to\n" 190 "the boot messages. Press [Scroll Lock] again to return."); 191 i = DITEM_FAILURE; 192 } 193 else { 194 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 195 free(menu); 196 } 197 } 198 } 199 if (DITEM_STATUS(i) != DITEM_FAILURE) { 200 if (variable_cmp(DISK_LABELLED, "written")) 201 variable_set2(DISK_LABELLED, "yes", 0); 202 } 203 return i; 204} 205 206int 207diskLabelCommit(dialogMenuItem *self) 208{ 209 char *cp; 210 int i; 211 212 /* Already done? */ 213 if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 214 i = DITEM_SUCCESS; 215 else if (!cp) { 216 msgConfirm("You must assign disk labels before this option can be used."); 217 i = DITEM_FAILURE; 218 } 219 /* The routine will guard against redundant writes, just as this one does */ 220 else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 221 i = DITEM_FAILURE; 222 else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 223 i = DITEM_FAILURE; 224 else { 225 msgInfo("All filesystem information written successfully."); 226 variable_set2(DISK_LABELLED, "written", 0); 227 i = DITEM_SUCCESS; 228 } 229 return i; 230} 231 232/* See if we're already using a desired partition name */ 233static Boolean 234check_conflict(char *name) 235{ 236 int i; 237 238 for (i = 0; label_chunk_info[i].c; i++) 239 if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) 240 && label_chunk_info[i].c->private_data 241 && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 242 return TRUE; 243 return FALSE; 244} 245 246/* How much space is in this FreeBSD slice? */ 247static int 248space_free(struct chunk *c) 249{ 250 struct chunk *c1; 251 int sz = c->size; 252 253 for (c1 = c->part; c1; c1 = c1->next) { 254 if (c1->type != unused) 255 sz -= c1->size; 256 } 257 if (sz < 0) 258 msgFatal("Partitions are larger than actual chunk??"); 259 return sz; 260} 261 262/* Snapshot the current situation into the displayed chunks structure */ 263static void 264record_label_chunks(Device **devs, Device *dev) 265{ 266 int i, j, p; 267 struct chunk *c1, *c2; 268 Disk *d; 269 270 j = p = 0; 271 /* First buzz through and pick up the FreeBSD slices */ 272 for (i = 0; devs[i]; i++) { 273 if ((dev && devs[i] != dev) || !devs[i]->enabled) 274 continue; 275 d = (Disk *)devs[i]->private; 276 if (!d->chunks) 277 msgFatal("No chunk list found for %s!", d->name); 278 279 /* Put the slice entries first */ 280 for (c1 = d->chunks->part; c1; c1 = c1->next) { 281 if (c1->type == freebsd) { 282 label_chunk_info[j].type = PART_SLICE; 283 label_chunk_info[j].c = c1; 284 ++j; 285 } 286 } 287 } 288 289 /* Now run through again and get the FreeBSD partition entries */ 290 for (i = 0; devs[i]; i++) { 291 if (!devs[i]->enabled) 292 continue; 293 d = (Disk *)devs[i]->private; 294 /* Then buzz through and pick up the partitions */ 295 for (c1 = d->chunks->part; c1; c1 = c1->next) { 296 if (c1->type == freebsd) { 297 for (c2 = c1->part; c2; c2 = c2->next) { 298 if (c2->type == part) { 299 if (c2->subtype == FS_SWAP) 300 label_chunk_info[j].type = PART_SWAP; 301 else 302 label_chunk_info[j].type = PART_FILESYSTEM; 303 label_chunk_info[j].c = c2; 304 ++j; 305 } 306 } 307 } 308 else if (c1->type == fat) { 309 label_chunk_info[j].type = PART_FAT; 310 label_chunk_info[j].c = c1; 311 ++j; 312 } 313 } 314 } 315 label_chunk_info[j].c = NULL; 316 if (here >= j) { 317 here = j ? j - 1 : 0; 318 } 319} 320 321/* A new partition entry */ 322static PartInfo * 323new_part(char *mpoint, Boolean newfs, u_long size) 324{ 325 PartInfo *ret; 326 327 if (!mpoint) 328 mpoint = "/change_me"; 329 330 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 331 sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX); 332 strcpy(ret->newfs_cmd, "newfs "); 333 strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS)); 334 ret->newfs = newfs; 335 ret->soft = strcmp(mpoint, "/") ? 1 : 0; 336 if (!size) 337 return ret; 338 return ret; 339} 340 341/* Get the mountpoint for a partition and save it away */ 342static PartInfo * 343get_mountpoint(struct chunk *old) 344{ 345 char *val; 346 PartInfo *tmp; 347 348 if (old && old->private_data) 349 tmp = old->private_data; 350 else 351 tmp = NULL; 352 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 353 if (!val || !*val) { 354 if (!old) 355 return NULL; 356 else { 357 free(old->private_data); 358 old->private_data = NULL; 359 } 360 return NULL; 361 } 362 363 /* Is it just the same value? */ 364 if (tmp && !strcmp(tmp->mountpoint, val)) 365 return NULL; 366 367 /* Did we use it already? */ 368 if (check_conflict(val)) { 369 msgConfirm("You already have a mount point for %s assigned!", val); 370 return NULL; 371 } 372 373 /* Is it bogus? */ 374 if (*val != '/') { 375 msgConfirm("Mount point must start with a / character"); 376 return NULL; 377 } 378 379 /* Is it going to be mounted on root? */ 380 if (!strcmp(val, "/")) { 381 if (old) 382 old->flags |= CHUNK_IS_ROOT; 383 } 384 else if (old) 385 old->flags &= ~CHUNK_IS_ROOT; 386 387 safe_free(tmp); 388 val = string_skipwhite(string_prune(val)); 389 tmp = new_part(val, TRUE, 0); 390 if (old) { 391 old->private_data = tmp; 392 old->private_free = safe_free; 393 } 394 return tmp; 395} 396 397/* Get the type of the new partiton */ 398static PartType 399get_partition_type(void) 400{ 401 char selection[20]; 402 int i; 403 static unsigned char *fs_types[] = { 404 "FS", 405 "A file system", 406 "Swap", 407 "A swap partition.", 408 }; 409 WINDOW *w = savescr(); 410 411 i = dialog_menu("Please choose a partition type", 412 "If you want to use this partition for swap space, select Swap.\n" 413 "If you want to put a filesystem on it, choose FS.", 414 -1, -1, 2, 2, fs_types, selection, NULL, NULL); 415 restorescr(w); 416 if (!i) { 417 if (!strcmp(selection, "FS")) 418 return PART_FILESYSTEM; 419 else if (!strcmp(selection, "Swap")) 420 return PART_SWAP; 421 } 422 return PART_NONE; 423} 424 425/* If the user wants a special newfs command for this, set it */ 426static void 427getNewfsCmd(PartInfo *p) 428{ 429 char *val; 430 431 val = msgGetInput(p->newfs_cmd, 432 "Please enter the newfs command and options you'd like to use in\n" 433 "creating this file system."); 434 if (val) 435 sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 436} 437 438#define MAX_MOUNT_NAME 9 439 440#define PART_PART_COL 0 441#define PART_MOUNT_COL 10 442#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 443#define PART_NEWFS_COL (PART_SIZE_COL + 8) 444#define PART_OFF 38 445 446#define TOTAL_AVAIL_LINES (10) 447#define PSLICE_SHOWABLE (4) 448 449 450/* stick this all up on the screen */ 451static void 452print_label_chunks(void) 453{ 454 int i, j, srow, prow, pcol; 455 int sz; 456 char clrmsg[80]; 457 int ChunkPartStartRow; 458 WINDOW *ChunkWin; 459 460 /********************************************************/ 461 /*** These values are for controling screen resources ***/ 462 /*** Each label line holds up to 2 labels, so beware! ***/ 463 /*** strategy will be to try to always make sure the ***/ 464 /*** highlighted label is in the active display area. ***/ 465 /********************************************************/ 466 int pslice_max, label_max; 467 int pslice_count, label_count, label_focus_found, pslice_focus_found; 468 469 attrset(A_REVERSE); 470 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 471 attrset(A_NORMAL); 472 473 /*** Count the number of parition slices ***/ 474 pslice_count = 0; 475 for (i = 0; label_chunk_info[i].c ; i++) { 476 if (label_chunk_info[i].type == PART_SLICE) 477 ++pslice_count; 478 } 479 pslice_max = pslice_count; 480 481 /*** 4 line max for partition slices ***/ 482 if (pslice_max > PSLICE_SHOWABLE) { 483 pslice_max = PSLICE_SHOWABLE; 484 } 485 ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 486 487 /*** View partition slices modulo pslice_max ***/ 488 label_max = TOTAL_AVAIL_LINES - pslice_max; 489 490 for (i = 0; i < 2; i++) { 491 mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 492 mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 493 494 mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 495 mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 496 497 mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); 498 mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); 499 500 mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 501 mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 502 } 503 srow = CHUNK_SLICE_START_ROW; 504 prow = 0; 505 pcol = 0; 506 507 /*** these variables indicate that the focused item is shown currently ***/ 508 label_focus_found = 0; 509 pslice_focus_found = 0; 510 511 label_count = 0; 512 pslice_count = 0; 513 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 514 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 515 516 ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 517 518 wclear(ChunkWin); 519 /*** wrefresh(ChunkWin); ***/ 520 521 for (i = 0; label_chunk_info[i].c; i++) { 522 /* Is it a slice entry displayed at the top? */ 523 if (label_chunk_info[i].type == PART_SLICE) { 524 /*** This causes the new pslice to replace the previous display ***/ 525 /*** focus must remain on the most recently active pslice ***/ 526 if (pslice_count == pslice_max) { 527 if (pslice_focus_found) { 528 /*** This is where we can mark the more following ***/ 529 attrset(A_BOLD); 530 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 531 attrset(A_NORMAL); 532 continue; 533 } 534 else { 535 /*** this is where we set the more previous ***/ 536 attrset(A_BOLD); 537 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 538 attrset(A_NORMAL); 539 pslice_count = 0; 540 srow = CHUNK_SLICE_START_ROW; 541 } 542 } 543 544 sz = space_free(label_chunk_info[i].c); 545 if (i == here) 546 attrset(ATTR_SELECTED); 547 if (i == pslice_focus) 548 pslice_focus_found = -1; 549 550 mvprintw(srow++, 0, 551 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 552 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, 553 sz, (sz / ONE_MEG)); 554 attrset(A_NORMAL); 555 clrtoeol(); 556 move(0, 0); 557 /*** refresh(); ***/ 558 ++pslice_count; 559 } 560 /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 561 else { 562 char onestr[PART_OFF], num[10], *mountpoint, newfs[10]; 563 564 /* 565 * We copy this into a blank-padded string so that it looks like 566 * a solid bar in reverse-video 567 */ 568 memset(onestr, ' ', PART_OFF - 1); 569 onestr[PART_OFF - 1] = '\0'; 570 571 /*** Track how many labels have been displayed ***/ 572 if (label_count == ((label_max - 1 ) * 2)) { 573 if (label_focus_found) { 574 continue; 575 } 576 else { 577 label_count = 0; 578 prow = 0; 579 pcol = 0; 580 } 581 } 582 583 /* Go for two columns if we've written one full columns worth */ 584 /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 585 if (label_count == label_max - 1) { 586 pcol = PART_OFF; 587 prow = 0; 588 } 589 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 590 /* If it's a filesystem, display the mountpoint */ 591 if (label_chunk_info[i].c->private_data 592 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 593 mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 594 else if (label_chunk_info[i].type == PART_SWAP) 595 mountpoint = "swap"; 596 else 597 mountpoint = "<none>"; 598 599 /* Now display the newfs field */ 600 if (label_chunk_info[i].type == PART_FAT) 601 strcpy(newfs, "DOS"); 602 else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) { 603 strcpy(newfs, "UFS"); 604 strcat(newfs, 605 ((PartInfo *)label_chunk_info[i].c->private_data)->soft ? 606 "+S" : " "); 607 strcat(newfs, 608 ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? 609 " Y" : " N"); 610 } 611 else if (label_chunk_info[i].type == PART_SWAP) 612 strcpy(newfs, "SWAP"); 613 else 614 strcpy(newfs, "*"); 615 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 616 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 617 snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 618 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 619 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 620 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 621 if (i == label_focus) { 622 label_focus_found = -1; 623 wattrset(ChunkWin, A_BOLD); 624 } 625 if (i == here) 626 wattrset(ChunkWin, ATTR_SELECTED); 627 628 /*** lazy man's way of expensively padding this string ***/ 629 while (strlen(onestr) < 37) 630 strcat(onestr, " "); 631 632 mvwaddstr(ChunkWin, prow, pcol, onestr); 633 wattrset(ChunkWin, A_NORMAL); 634 move(0, 0); 635 ++prow; 636 ++label_count; 637 } 638 } 639 640 /*** this will erase all the extra stuff ***/ 641 memset(clrmsg, ' ', 37); 642 clrmsg[37] = '\0'; 643 644 while (pslice_count < pslice_max) { 645 mvprintw(srow++, 0, clrmsg); 646 clrtoeol(); 647 ++pslice_count; 648 } 649 while (label_count < (2 * (label_max - 1))) { 650 mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 651 ++label_count; 652 if (prow == (label_max - 1)) { 653 prow = 0; 654 pcol = PART_OFF; 655 } 656 } 657 refresh(); 658 wrefresh(ChunkWin); 659} 660 661static void 662print_command_summary(void) 663{ 664 mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 665 mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 666 if (!RunningAsInit) 667 mvprintw(18, 47, "W = Write"); 668 mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates"); 669 mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge"); 670 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 671 move(0, 0); 672} 673 674static void 675clear_wins(void) 676{ 677 extern void print_label_chunks(); 678 clear(); 679 print_label_chunks(); 680} 681 682#ifdef __alpha__ 683 684/* 685 * If there isn't a freebsd chunk already (i.e. there is no label), 686 * dedicate the disk. 687 */ 688static void 689maybe_dedicate(Disk* d) 690{ 691 struct chunk *c; 692 693 for (c = d->chunks->part; c; c = c->next) { 694 if (c->type == freebsd) 695 break; 696 } 697 698 if (!c) { 699 msgDebug("dedicating disk"); 700 All_FreeBSD(d, 1); 701 } 702} 703 704#endif 705 706static int 707diskLabel(Device *dev) 708{ 709 int sz, key = 0; 710 Boolean labeling; 711 char *msg = NULL; 712 PartInfo *p, *oldp; 713 PartType type; 714 Device **devs; 715#ifdef __alpha__ 716 int i; 717#endif 718 WINDOW *w = savescr(); 719 720 label_focus = 0; 721 pslice_focus = 0; 722 here = 0; 723 724 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 725 if (!devs) { 726 msgConfirm("No disks found!"); 727 restorescr(w); 728 return DITEM_FAILURE; 729 } 730 labeling = TRUE; 731 keypad(stdscr, TRUE); 732#ifdef __alpha__ 733 for (i = 0; devs[i]; i++) { 734 maybe_dedicate((Disk*) devs[i]->private); 735 } 736#endif 737 record_label_chunks(devs, dev); 738 739 clear(); 740 while (labeling) { 741 char *cp; 742 int rflags = DELCHUNK_NORMAL; 743 744 print_label_chunks(); 745 print_command_summary(); 746 if (msg) { 747 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 748 clrtoeol(); 749 beep(); 750 msg = NULL; 751 } 752 else { 753 move(23, 0); 754 clrtoeol(); 755 } 756 757 refresh(); 758 key = getch(); 759 switch (toupper(key)) { 760 int i; 761 static char _msg[40]; 762 763 case '\014': /* ^L */ 764 clear_wins(); 765 break; 766 767 case '\020': /* ^P */ 768 case KEY_UP: 769 case '-': 770 if (here != 0) 771 --here; 772 else 773 while (label_chunk_info[here + 1].c) 774 ++here; 775 break; 776 777 case '\016': /* ^N */ 778 case KEY_DOWN: 779 case '+': 780 case '\r': 781 case '\n': 782 if (label_chunk_info[here + 1].c) 783 ++here; 784 else 785 here = 0; 786 break; 787 788 case KEY_HOME: 789 here = 0; 790 break; 791 792 case KEY_END: 793 while (label_chunk_info[here + 1].c) 794 ++here; 795 break; 796 797 case KEY_F(1): 798 case '?': 799 systemDisplayHelp("partition"); 800 clear_wins(); 801 break; 802 803 case 'A': 804 if (label_chunk_info[here].type != PART_SLICE) { 805 msg = "You can only do this in a disk slice (at top of screen)"; 806 break; 807 } 808 /* 809 * Generate standard partitions automatically. If we do not 810 * have sufficient space we attempt to scale-down the size 811 * of the partitions within certain bounds. 812 */ 813 { 814 int perc; 815 int req = 0; 816 817 for (perc = 100; perc > 0; perc -= 5) { 818 req = 0; /* reset for each loop */ 819 if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL) 820 break; 821 } 822 if (msg) { 823 if (req) { 824 msgConfirm(msg); 825 clear_wins(); 826 msg = NULL; 827 } 828 } 829 } 830 break; 831 832 case 'C': 833 if (label_chunk_info[here].type != PART_SLICE) { 834 msg = "You can only do this in a master partition (see top of screen)"; 835 break; 836 } 837 sz = space_free(label_chunk_info[here].c); 838 if (sz <= FS_MIN_SIZE) { 839 msg = "Not enough space to create an additional FreeBSD partition"; 840 break; 841 } 842 else { 843 char *val; 844 int size; 845 struct chunk *tmp; 846 char osize[80]; 847 u_long flags = 0; 848 849 sprintf(osize, "%d", sz); 850 val = msgGetInput(osize, 851 "Please specify the partition size in blocks or append a trailing G for\n" 852 "gigabytes, M for megabytes, or C for cylinders.\n" 853 "%d blocks (%dMB) are free.", 854 sz, sz / ONE_MEG); 855 if (!val || (size = strtol(val, &cp, 0)) <= 0) { 856 clear_wins(); 857 break; 858 } 859 860 if (*cp) { 861 if (toupper(*cp) == 'M') 862 size *= ONE_MEG; 863 else if (toupper(*cp) == 'G') 864 size *= ONE_GIG; 865 else if (toupper(*cp) == 'C') 866 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 867 } 868 if (size <= FS_MIN_SIZE) { 869 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 870 clear_wins(); 871 break; 872 } 873 type = get_partition_type(); 874 if (type == PART_NONE) { 875 clear_wins(); 876 beep(); 877 break; 878 } 879 880 if (type == PART_FILESYSTEM) { 881 if ((p = get_mountpoint(NULL)) == NULL) { 882 clear_wins(); 883 beep(); 884 break; 885 } 886 else if (!strcmp(p->mountpoint, "/")) 887 flags |= CHUNK_IS_ROOT; 888 else 889 flags &= ~CHUNK_IS_ROOT; 890 } 891 else 892 p = NULL; 893 894 if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) { 895 msgConfirm("Warning: This is smaller than the recommended size for a\n" 896 "root partition. For a variety of reasons, root\n" 897 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 898 } 899 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 900 label_chunk_info[here].c, 901 size, part, 902 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 903 flags); 904 if (!tmp) { 905 msgConfirm("Unable to create the partition. Too big?"); 906 clear_wins(); 907 break; 908 } 909 910#ifdef __alpha__ 911 /* 912 * SRM requires that the root partition is at the 913 * begining of the disk and cannot boot otherwise. 914 * Warn Alpha users if they are about to shoot themselves in 915 * the foot in this way. 916 * 917 * Since partitions may not start precisely at offset 0 we 918 * check for a "close to 0" instead. :-( 919 */ 920 if ((flags & CHUNK_IS_ROOT) && (tmp->offset > 1024)) { 921 msgConfirm("Your root partition `a' does not seem to be the first\n" 922 "partition. The Alpha's firmware can only boot from the\n" 923 "first partition. So it is unlikely that your current\n" 924 "disk layout will be bootable boot after installation.\n" 925 "\n" 926 "Please allocate the root partition before allocating\n" 927 "any others.\n"); 928 } 929#endif /* alpha */ 930 931 if (type != PART_SWAP) { 932 /* This is needed to tell the newfs -u about the size */ 933 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 934 safe_free(p); 935 } 936 else 937 tmp->private_data = p; 938 tmp->private_free = safe_free; 939 if (variable_cmp(DISK_LABELLED, "written")) 940 variable_set2(DISK_LABELLED, "yes", 0); 941 record_label_chunks(devs, dev); 942 clear_wins(); 943 /* This is where we assign focus to new label so it shows. */ 944 { 945 int i; 946 label_focus = -1; 947 for (i = 0; label_chunk_info[i].c; ++i) { 948 if (label_chunk_info[i].c == tmp) { 949 label_focus = i; 950 break; 951 } 952 } 953 if (label_focus == -1) 954 label_focus = i - 1; 955 } 956 } 957 break; 958 959 case KEY_DC: 960 case 'R': /* recover space (delete w/ recover) */ 961 /* 962 * Delete the partition w/ space recovery. 963 */ 964 rflags = DELCHUNK_RECOVER; 965 /* fall through */ 966 case 'D': /* delete */ 967 if (label_chunk_info[here].type == PART_SLICE) { 968 msg = MSG_NOT_APPLICABLE; 969 break; 970 } 971 else if (label_chunk_info[here].type == PART_FAT) { 972 msg = "Use the Disk Partition Editor to delete DOS partitions"; 973 break; 974 } 975 Delete_Chunk2(label_chunk_info[here].c->disk, label_chunk_info[here].c, rflags); 976 if (variable_cmp(DISK_LABELLED, "written")) 977 variable_set2(DISK_LABELLED, "yes", 0); 978 record_label_chunks(devs, dev); 979 break; 980 981 case 'M': /* mount */ 982 switch(label_chunk_info[here].type) { 983 case PART_SLICE: 984 msg = MSG_NOT_APPLICABLE; 985 break; 986 987 case PART_SWAP: 988 msg = "You don't need to specify a mountpoint for a swap partition."; 989 break; 990 991 case PART_FAT: 992 case PART_FILESYSTEM: 993 oldp = label_chunk_info[here].c->private_data; 994 p = get_mountpoint(label_chunk_info[here].c); 995 if (p) { 996 if (!oldp) 997 p->newfs = FALSE; 998 if (label_chunk_info[here].type == PART_FAT 999 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 1000 || !strcmp(p->mountpoint, "/var"))) { 1001 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 1002 strcpy(p->mountpoint, "/bogus"); 1003 } 1004 } 1005 if (variable_cmp(DISK_LABELLED, "written")) 1006 variable_set2(DISK_LABELLED, "yes", 0); 1007 record_label_chunks(devs, dev); 1008 clear_wins(); 1009 break; 1010 1011 default: 1012 msgFatal("Bogus partition under cursor???"); 1013 break; 1014 } 1015 break; 1016 1017 case 'N': /* Set newfs options */ 1018 if (label_chunk_info[here].c->private_data && 1019 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 1020 getNewfsCmd(label_chunk_info[here].c->private_data); 1021 else 1022 msg = MSG_NOT_APPLICABLE; 1023 clear_wins(); 1024 break; 1025 1026 case 'S': /* Toggle soft updates flag */ 1027 if (label_chunk_info[here].type == PART_FILESYSTEM) { 1028 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 1029 if (pi) 1030 pi->soft = !pi->soft; 1031 else 1032 msg = MSG_NOT_APPLICABLE; 1033 } 1034 else 1035 msg = MSG_NOT_APPLICABLE; 1036 break; 1037 1038 case 'T': /* Toggle newfs state */ 1039 if ((label_chunk_info[here].type == PART_FILESYSTEM) && 1040 (label_chunk_info[here].c->private_data)) { 1041 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 1042 if (!pi->newfs) 1043 label_chunk_info[here].c->flags |= CHUNK_NEWFS; 1044 else 1045 label_chunk_info[here].c->flags &= ~CHUNK_NEWFS; 1046 1047 label_chunk_info[here].c->private_data = 1048 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 1049 if (pi && pi->soft) 1050 ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1; 1051 safe_free(pi); 1052 label_chunk_info[here].c->private_free = safe_free; 1053 if (variable_cmp(DISK_LABELLED, "written")) 1054 variable_set2(DISK_LABELLED, "yes", 0); 1055 } 1056 else 1057 msg = MSG_NOT_APPLICABLE; 1058 break; 1059 1060 case 'U': 1061 clear(); 1062 if (!variable_cmp(DISK_LABELLED, "written")) { 1063 msgConfirm("You've already written out your changes -\n" 1064 "it's too late to undo!"); 1065 } 1066 else if (!msgNoYes("Are you SURE you want to Undo everything?")) { 1067 variable_unset(DISK_PARTITIONED); 1068 variable_unset(DISK_LABELLED); 1069 for (i = 0; devs[i]; i++) { 1070 Disk *d; 1071 1072 if (!devs[i]->enabled) 1073 continue; 1074 else if ((d = Open_Disk(devs[i]->name)) != NULL) { 1075 Free_Disk(devs[i]->private); 1076 devs[i]->private = d; 1077 diskPartition(devs[i]); 1078 } 1079 } 1080 record_label_chunks(devs, dev); 1081 } 1082 clear_wins(); 1083 break; 1084 1085 case 'W': 1086 if (!variable_cmp(DISK_LABELLED, "written")) { 1087 msgConfirm("You've already written out your changes - if you\n" 1088 "wish to overwrite them, you'll have to restart\n" 1089 "sysinstall first."); 1090 } 1091 else if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" 1092 "installation. If you are installing FreeBSD for the first time\n" 1093 "then you should simply type Q when you're finished here and your\n" 1094 "changes will be committed in one batch automatically at the end of\n" 1095 "these questions.\n\n" 1096 "Are you absolutely sure you want to do this now?")) { 1097 variable_set2(DISK_LABELLED, "yes", 0); 1098 diskLabelCommit(NULL); 1099 } 1100 clear_wins(); 1101 break; 1102 1103 case '|': 1104 if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n" 1105 "This is an entirely undocumented feature which you are not\n" 1106 "expected to understand!")) { 1107 int i; 1108 Device **devs; 1109 1110 dialog_clear(); 1111 end_dialog(); 1112 DialogActive = FALSE; 1113 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 1114 if (!devs) { 1115 msgConfirm("Can't find any disk devices!"); 1116 break; 1117 } 1118 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 1119 if (devs[i]->enabled) 1120 slice_wizard(((Disk *)devs[i]->private)); 1121 } 1122 if (variable_cmp(DISK_LABELLED, "written")) 1123 variable_set2(DISK_LABELLED, "yes", 0); 1124 DialogActive = TRUE; 1125 record_label_chunks(devs, dev); 1126 clear_wins(); 1127 } 1128 else 1129 msg = "A most prudent choice!"; 1130 break; 1131 1132 case '\033': /* ESC */ 1133 case 'Q': 1134 labeling = FALSE; 1135 break; 1136 1137 default: 1138 beep(); 1139 sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 1140 msg = _msg; 1141 break; 1142 } 1143 if (label_chunk_info[here].type == PART_SLICE) 1144 pslice_focus = here; 1145 else 1146 label_focus = here; 1147 } 1148 restorescr(w); 1149 return DITEM_SUCCESS; 1150} 1151 1152static __inline int 1153requested_part_size(char *varName, int nom, int def, int perc) 1154{ 1155 char *cp; 1156 int sz; 1157 1158 if ((cp = variable_get(VAR_ROOT_SIZE)) != NULL) 1159 sz = atoi(cp); 1160 else 1161 sz = nom + (def - nom) * perc / 100; 1162 return(sz * ONE_MEG); 1163} 1164 1165/* 1166 * Attempt to auto-label the disk. 'perc' (0-100) scales 1167 * the size of the various partitions within appropriate 1168 * bounds (NOMINAL through DEFAULT sizes). The procedure 1169 * succeeds of NULL is returned. A non-null return message 1170 * is either a failure-status message (*req == 0), or 1171 * a confirmation requestor (*req == 1). *req is 0 on 1172 * entry to this call. 1173 * 1174 * We autolabel the following partitions: /, swap, /var, /tmp, /usr, 1175 * and /home. /home receives any extra left over disk space. 1176 */ 1177static char * 1178try_auto_label(Device **devs, Device *dev, int perc, int *req) 1179{ 1180 int sz; 1181 struct chunk *root_chunk = NULL; 1182 struct chunk *swap_chunk = NULL; 1183 struct chunk *usr_chunk = NULL; 1184 struct chunk *var_chunk = NULL; 1185 struct chunk *tmp_chunk = NULL; 1186 struct chunk *home_chunk = NULL; 1187 int mib[2]; 1188 unsigned int physmem; 1189 size_t size; 1190 Chunk *rootdev, *swapdev, *usrdev, *vardev; 1191 Chunk *tmpdev, *homedev; 1192 char *msg = NULL; 1193 1194 sz = space_free(label_chunk_info[here].c); 1195 if (sz <= FS_MIN_SIZE) 1196 return("Not enough free space to create a new partition in the slice"); 1197 1198 (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, 1199 &vardev, &tmpdev, &homedev); 1200 if (!rootdev) { 1201 sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc); 1202 1203 root_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1204 label_chunk_info[here].c, sz, part, 1205 FS_BSDFFS, CHUNK_IS_ROOT | CHUNK_AUTO_SIZE); 1206 if (!root_chunk) { 1207 *req = 1; 1208 msg = "Unable to create the root partition. Too big?"; 1209 goto done; 1210 } 1211 root_chunk->private_data = new_part("/", TRUE, root_chunk->size); 1212 root_chunk->private_free = safe_free; 1213 root_chunk->flags |= CHUNK_NEWFS; 1214 record_label_chunks(devs, dev); 1215 } 1216 if (!swapdev) { 1217 sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc); 1218 if (sz == 0) { 1219 int nom; 1220 int def; 1221 1222 mib[0] = CTL_HW; 1223 mib[1] = HW_PHYSMEM; 1224 size = sizeof physmem; 1225 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 1226 def = 2 * (int)(physmem / 512); 1227 if (def < SWAP_MIN_SIZE * ONE_MEG) 1228 def = SWAP_MIN_SIZE * ONE_MEG; 1229 if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG) 1230 def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG; 1231 nom = (int)(physmem / 512) / 2; 1232 sz = nom + (def - nom) * perc / 100; 1233 } 1234 swap_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1235 label_chunk_info[here].c, sz, part, 1236 FS_SWAP, CHUNK_AUTO_SIZE); 1237 if (!swap_chunk) { 1238 *req = 1; 1239 msg = "Unable to create the swap partition. Too big?"; 1240 goto done; 1241 } 1242 swap_chunk->private_data = 0; 1243 swap_chunk->private_free = safe_free; 1244 record_label_chunks(devs, dev); 1245 } 1246 if (!vardev) { 1247 sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, VAR_DEFAULT_SIZE, perc); 1248 1249 var_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1250 label_chunk_info[here].c, sz, part, 1251 FS_BSDFFS, CHUNK_AUTO_SIZE); 1252 if (!var_chunk) { 1253 *req = 1; 1254 msg = "Not enough free space for /var - you will need to\n" 1255 "partition your disk manually with a custom install!"; 1256 goto done; 1257 } 1258 var_chunk->private_data = new_part("/var", TRUE, var_chunk->size); 1259 var_chunk->private_free = safe_free; 1260 var_chunk->flags |= CHUNK_NEWFS; 1261 record_label_chunks(devs, dev); 1262 } 1263 if (!tmpdev && !variable_get(VAR_NO_TMP)) { 1264 sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc); 1265 1266 tmp_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1267 label_chunk_info[here].c, sz, part, 1268 FS_BSDFFS, CHUNK_AUTO_SIZE); 1269 if (!tmp_chunk) { 1270 *req = 1; 1271 msg = "Not enough free space for /tmp - you will need to\n" 1272 "partition your disk manually with a custom install!"; 1273 goto done; 1274 } 1275 tmp_chunk->private_data = new_part("/tmp", TRUE, tmp_chunk->size); 1276 tmp_chunk->private_free = safe_free; 1277 tmp_chunk->flags |= CHUNK_NEWFS; 1278 record_label_chunks(devs, dev); 1279 } 1280 if (!usrdev && !variable_get(VAR_NO_USR)) { 1281 sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc); 1282#if AUTO_HOME == 0 1283 sz = space_free(label_chunk_info[here].c); 1284#endif 1285 if (sz) { 1286 if (sz < (USR_MIN_SIZE * ONE_MEG)) { 1287 *req = 1; 1288 msg = "Not enough free space for /usr - you will need to\n" 1289 "partition your disk manually with a custom install!"; 1290 } 1291 1292 usr_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1293 label_chunk_info[here].c, sz, part, 1294 FS_BSDFFS, CHUNK_AUTO_SIZE); 1295 if (!usr_chunk) { 1296 msg = "Unable to create the /usr partition. Not enough space?\n" 1297 "You will need to partition your disk manually with a custom install!"; 1298 goto done; 1299 } 1300 usr_chunk->private_data = new_part("/usr", TRUE, usr_chunk->size); 1301 usr_chunk->private_free = safe_free; 1302 usr_chunk->flags |= CHUNK_NEWFS; 1303 record_label_chunks(devs, dev); 1304 } 1305 } 1306#if AUTO_HOME == 1 1307 if (!homedev && !variable_get(VAR_NO_HOME)) { 1308 sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc); 1309 if (sz < space_free(label_chunk_info[here].c)) 1310 sz = space_free(label_chunk_info[here].c); 1311 if (sz) { 1312 if (sz < (HOME_MIN_SIZE * ONE_MEG)) { 1313 *req = 1; 1314 msg = "Not enough free space for /home - you will need to\n" 1315 "partition your disk manually with a custom install!"; 1316 goto done; 1317 } 1318 1319 home_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1320 label_chunk_info[here].c, sz, part, 1321 FS_BSDFFS, CHUNK_AUTO_SIZE); 1322 if (!home_chunk) { 1323 msg = "Unable to create the /home partition. Not enough space?\n" 1324 "You will need to partition your disk manually with a custom install!"; 1325 goto done; 1326 } 1327 home_chunk->private_data = new_part("/home", TRUE, home_chunk->size); 1328 home_chunk->private_free = safe_free; 1329 home_chunk->flags |= CHUNK_NEWFS; 1330 record_label_chunks(devs, dev); 1331 } 1332 } 1333#endif 1334 1335 /* At this point, we're reasonably "labelled" */ 1336 if (variable_cmp(DISK_LABELLED, "written")) 1337 variable_set2(DISK_LABELLED, "yes", 0); 1338 1339done: 1340 if (msg) { 1341 if (root_chunk) 1342 Delete_Chunk(root_chunk->disk, root_chunk); 1343 if (swap_chunk) 1344 Delete_Chunk(swap_chunk->disk, swap_chunk); 1345 if (var_chunk) 1346 Delete_Chunk(var_chunk->disk, var_chunk); 1347 if (tmp_chunk) 1348 Delete_Chunk(tmp_chunk->disk, tmp_chunk); 1349 if (usr_chunk) 1350 Delete_Chunk(usr_chunk->disk, usr_chunk); 1351 if (home_chunk) 1352 Delete_Chunk(home_chunk->disk, home_chunk); 1353 record_label_chunks(devs, dev); 1354 } 1355 return(msg); 1356} 1357 1358static int 1359diskLabelNonInteractive(Device *dev) 1360{ 1361 char *cp; 1362 PartType type; 1363 PartInfo *p; 1364 u_long flags = 0; 1365 int i, status; 1366 Device **devs; 1367 Disk *d; 1368 1369 status = DITEM_SUCCESS; 1370 cp = variable_get(VAR_DISK); 1371 if (!cp) { 1372 msgConfirm("diskLabel: No disk selected - can't label automatically."); 1373 return DITEM_FAILURE; 1374 } 1375 devs = deviceFind(cp, DEVICE_TYPE_DISK); 1376 if (!devs) { 1377 msgConfirm("diskLabel: No disk device %s found!", cp); 1378 return DITEM_FAILURE; 1379 } 1380 if (dev) 1381 d = dev->private; 1382 else 1383 d = devs[0]->private; 1384#ifdef __alpha__ 1385 maybe_dedicate(d); 1386#endif 1387 record_label_chunks(devs, dev); 1388 for (i = 0; label_chunk_info[i].c; i++) { 1389 Chunk *c1 = label_chunk_info[i].c; 1390 1391 if (label_chunk_info[i].type == PART_SLICE) { 1392 char name[512]; 1393 int entries = 1; 1394 1395 while (entries) { 1396 snprintf(name, sizeof name, "%s-%d", c1->name, entries); 1397 if ((cp = variable_get(name)) != NULL) { 1398 int sz, soft = 0; 1399 char typ[10], mpoint[50]; 1400 1401 if (sscanf(cp, "%s %d %s %d", typ, &sz, mpoint, &soft) < 3) { 1402 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 1403 status = DITEM_FAILURE; 1404 continue; 1405 } 1406 else { 1407 Chunk *tmp; 1408 1409 if (!strcmp(typ, "swap")) { 1410 type = PART_SWAP; 1411 strcpy(mpoint, "SWAP"); 1412 } 1413 else { 1414 type = PART_FILESYSTEM; 1415 if (!strcmp(mpoint, "/")) 1416 flags |= CHUNK_IS_ROOT; 1417 else 1418 flags &= ~CHUNK_IS_ROOT; 1419 } 1420 if (!sz) 1421 sz = space_free(c1); 1422 if (sz > space_free(c1)) { 1423 msgConfirm("Not enough free space to create partition: %s", mpoint); 1424 status = DITEM_FAILURE; 1425 continue; 1426 } 1427 if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 1428 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 1429 msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 1430 status = DITEM_FAILURE; 1431 break; 1432 } 1433 else { 1434 tmp->private_data = new_part(mpoint, TRUE, sz); 1435 tmp->private_free = safe_free; 1436 ((PartInfo *)tmp->private_data)->soft = soft; 1437 status = DITEM_SUCCESS; 1438 } 1439 } 1440 entries++; 1441 } 1442 else { 1443 /* No more matches, leave the loop */ 1444 entries = 0; 1445 } 1446 } 1447 } 1448 else { 1449 /* Must be something we can set a mountpoint for */ 1450 cp = variable_get(c1->name); 1451 if (cp) { 1452 char mpoint[50], do_newfs[8]; 1453 Boolean newfs = FALSE; 1454 1455 do_newfs[0] = '\0'; 1456 if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 1457 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 1458 status = DITEM_FAILURE; 1459 continue; 1460 } 1461 newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 1462 if (c1->private_data) { 1463 p = c1->private_data; 1464 p->newfs = newfs; 1465 strcpy(p->mountpoint, mpoint); 1466 } 1467 else { 1468 c1->private_data = new_part(mpoint, newfs, 0); 1469 c1->private_free = safe_free; 1470 } 1471 if (!strcmp(mpoint, "/")) 1472 c1->flags |= CHUNK_IS_ROOT; 1473 else 1474 c1->flags &= ~CHUNK_IS_ROOT; 1475 } 1476 } 1477 } 1478 if (status == DITEM_SUCCESS) 1479 variable_set2(DISK_LABELLED, "yes", 0); 1480 return status; 1481} 1482