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