label.c revision 87583
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 87583 2001-12-10 02:18:05Z 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 TMP_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 TMP_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 TMP_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 if (!pi->newfs) 1031 label_chunk_info[here].c->flags |= CHUNK_NEWFS; 1032 else 1033 label_chunk_info[here].c->flags &= ~CHUNK_NEWFS; 1034 1035 label_chunk_info[here].c->private_data = 1036 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 1037 if (pi && pi->soft) 1038 ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1; 1039 safe_free(pi); 1040 label_chunk_info[here].c->private_free = safe_free; 1041 if (variable_cmp(DISK_LABELLED, "written")) 1042 variable_set2(DISK_LABELLED, "yes", 0); 1043 } 1044 else 1045 msg = MSG_NOT_APPLICABLE; 1046 break; 1047 1048 case 'U': 1049 clear(); 1050 if (!variable_cmp(DISK_LABELLED, "written")) { 1051 msgConfirm("You've already written out your changes -\n" 1052 "it's too late to undo!"); 1053 } 1054 else if (!msgNoYes("Are you SURE you want to Undo everything?")) { 1055 variable_unset(DISK_PARTITIONED); 1056 variable_unset(DISK_LABELLED); 1057 for (i = 0; devs[i]; i++) { 1058 Disk *d; 1059 1060 if (!devs[i]->enabled) 1061 continue; 1062 else if ((d = Open_Disk(devs[i]->name)) != NULL) { 1063 Free_Disk(devs[i]->private); 1064 devs[i]->private = d; 1065 diskPartition(devs[i]); 1066 } 1067 } 1068 record_label_chunks(devs, dev); 1069 } 1070 clear_wins(); 1071 break; 1072 1073 case 'W': 1074 if (!variable_cmp(DISK_LABELLED, "written")) { 1075 msgConfirm("You've already written out your changes - if you\n" 1076 "wish to overwrite them, you'll have to restart\n" 1077 "sysinstall first."); 1078 } 1079 else if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" 1080 "installation. If you are installing FreeBSD for the first time\n" 1081 "then you should simply type Q when you're finished here and your\n" 1082 "changes will be committed in one batch automatically at the end of\n" 1083 "these questions.\n\n" 1084 "Are you absolutely sure you want to do this now?")) { 1085 variable_set2(DISK_LABELLED, "yes", 0); 1086 diskLabelCommit(NULL); 1087 } 1088 clear_wins(); 1089 break; 1090 1091 case '|': 1092 if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n" 1093 "This is an entirely undocumented feature which you are not\n" 1094 "expected to understand!")) { 1095 int i; 1096 Device **devs; 1097 1098 dialog_clear(); 1099 end_dialog(); 1100 DialogActive = FALSE; 1101 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 1102 if (!devs) { 1103 msgConfirm("Can't find any disk devices!"); 1104 break; 1105 } 1106 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 1107 if (devs[i]->enabled) 1108 slice_wizard(((Disk *)devs[i]->private)); 1109 } 1110 if (variable_cmp(DISK_LABELLED, "written")) 1111 variable_set2(DISK_LABELLED, "yes", 0); 1112 DialogActive = TRUE; 1113 record_label_chunks(devs, dev); 1114 clear_wins(); 1115 } 1116 else 1117 msg = "A most prudent choice!"; 1118 break; 1119 1120 case '\033': /* ESC */ 1121 case 'Q': 1122 labeling = FALSE; 1123 break; 1124 1125 default: 1126 beep(); 1127 sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 1128 msg = _msg; 1129 break; 1130 } 1131 if (label_chunk_info[here].type == PART_SLICE) 1132 pslice_focus = here; 1133 else 1134 label_focus = here; 1135 } 1136 restorescr(w); 1137 return DITEM_SUCCESS; 1138} 1139 1140static __inline int 1141requested_part_size(char *varName, int nom, int def, int perc) 1142{ 1143 char *cp; 1144 int sz; 1145 1146 if ((cp = variable_get(VAR_ROOT_SIZE)) != NULL) 1147 sz = atoi(cp); 1148 else 1149 sz = nom + (def - nom) * perc / 100; 1150 return(sz * ONE_MEG); 1151} 1152 1153/* 1154 * Attempt to auto-label the disk. 'perc' (0-100) scales 1155 * the size of the various partitions within appropriate 1156 * bounds (NOMINAL through DEFAULT sizes). The procedure 1157 * succeeds of NULL is returned. A non-null return message 1158 * is either a failure-status message (*req == 0), or 1159 * a confirmation requestor (*req == 1). *req is 0 on 1160 * entry to this call. 1161 * 1162 * We autolabel the following partitions: /, swap, /var, /tmp, /usr, 1163 * and /home. /home receives any extra left over disk space. 1164 */ 1165static char * 1166try_auto_label(Device **devs, Device *dev, int perc, int *req) 1167{ 1168 int sz; 1169 struct chunk *root_chunk = NULL; 1170 struct chunk *swap_chunk = NULL; 1171 struct chunk *usr_chunk = NULL; 1172 struct chunk *var_chunk = NULL; 1173 struct chunk *tmp_chunk = NULL; 1174 struct chunk *home_chunk = NULL; 1175 int mib[2]; 1176 unsigned int physmem; 1177 size_t size; 1178 Chunk *rootdev, *swapdev, *usrdev, *vardev; 1179 Chunk *tmpdev, *homedev; 1180 char *msg = NULL; 1181 1182 sz = space_free(label_chunk_info[here].c); 1183 if (sz <= FS_MIN_SIZE) 1184 return("Not enough free space to create a new partition in the slice"); 1185 1186 (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, 1187 &vardev, &tmpdev, &homedev); 1188 if (!rootdev) { 1189 sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc); 1190 1191 root_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1192 label_chunk_info[here].c, sz, part, 1193 FS_BSDFFS, CHUNK_IS_ROOT | CHUNK_AUTO_SIZE); 1194 if (!root_chunk) { 1195 *req = 1; 1196 msg = "Unable to create the root partition. Too big?"; 1197 goto done; 1198 } 1199 root_chunk->private_data = new_part("/", TRUE, root_chunk->size); 1200 root_chunk->private_free = safe_free; 1201 root_chunk->flags |= CHUNK_NEWFS; 1202 record_label_chunks(devs, dev); 1203 } 1204 if (!swapdev) { 1205 sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc); 1206 if (sz == 0) { 1207 int nom; 1208 int def; 1209 1210 mib[0] = CTL_HW; 1211 mib[1] = HW_PHYSMEM; 1212 size = sizeof physmem; 1213 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 1214 def = 2 * (int)(physmem / 512); 1215 if (def < SWAP_MIN_SIZE * ONE_MEG) 1216 def = SWAP_MIN_SIZE * ONE_MEG; 1217 if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG) 1218 def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG; 1219 nom = (int)(physmem / 512) / 2; 1220 sz = nom + (def - nom) * perc / 100; 1221 } 1222 swap_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1223 label_chunk_info[here].c, sz, part, 1224 FS_SWAP, CHUNK_AUTO_SIZE); 1225 if (!swap_chunk) { 1226 *req = 1; 1227 msg = "Unable to create the swap partition. Too big?"; 1228 goto done; 1229 } 1230 swap_chunk->private_data = 0; 1231 swap_chunk->private_free = safe_free; 1232 record_label_chunks(devs, dev); 1233 } 1234 if (!vardev) { 1235 sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, VAR_DEFAULT_SIZE, perc); 1236 1237 var_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1238 label_chunk_info[here].c, sz, part, 1239 FS_BSDFFS, CHUNK_AUTO_SIZE); 1240 if (!var_chunk) { 1241 *req = 1; 1242 msg = "Not enough free space for /var - you will need to\n" 1243 "partition your disk manually with a custom install!"; 1244 goto done; 1245 } 1246 var_chunk->private_data = new_part("/var", TRUE, var_chunk->size); 1247 var_chunk->private_free = safe_free; 1248 var_chunk->flags |= CHUNK_NEWFS; 1249 record_label_chunks(devs, dev); 1250 } 1251 if (!tmpdev && !variable_get(VAR_NO_TMP)) { 1252 sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc); 1253 1254 tmp_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1255 label_chunk_info[here].c, sz, part, 1256 FS_BSDFFS, CHUNK_AUTO_SIZE); 1257 if (!tmp_chunk) { 1258 *req = 1; 1259 msg = "Not enough free space for /tmp - you will need to\n" 1260 "partition your disk manually with a custom install!"; 1261 goto done; 1262 } 1263 tmp_chunk->private_data = new_part("/tmp", TRUE, tmp_chunk->size); 1264 tmp_chunk->private_free = safe_free; 1265 tmp_chunk->flags |= CHUNK_NEWFS; 1266 record_label_chunks(devs, dev); 1267 } 1268 if (!usrdev && !variable_get(VAR_NO_USR)) { 1269 sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc); 1270#if 0 1271 sz = space_free(label_chunk_info[here].c); 1272#endif 1273 if (sz) { 1274 if (sz < (USR_MIN_SIZE * ONE_MEG)) { 1275 *req = 1; 1276 msg = "Not enough free space for /usr - you will need to\n" 1277 "partition your disk manually with a custom install!"; 1278 } 1279 1280 usr_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1281 label_chunk_info[here].c, sz, part, 1282 FS_BSDFFS, CHUNK_AUTO_SIZE); 1283 if (!usr_chunk) { 1284 msg = "Unable to create the /usr partition. Not enough space?\n" 1285 "You will need to partition your disk manually with a custom install!"; 1286 goto done; 1287 } 1288 usr_chunk->private_data = new_part("/usr", TRUE, usr_chunk->size); 1289 usr_chunk->private_free = safe_free; 1290 usr_chunk->flags |= CHUNK_NEWFS; 1291 record_label_chunks(devs, dev); 1292 } 1293 } 1294 if (!homedev && !variable_get(VAR_NO_HOME)) { 1295 sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc); 1296 if (sz < space_free(label_chunk_info[here].c)) 1297 sz = space_free(label_chunk_info[here].c); 1298 if (sz) { 1299 if (sz < (HOME_MIN_SIZE * ONE_MEG)) { 1300 *req = 1; 1301 msg = "Not enough free space for /home - you will need to\n" 1302 "partition your disk manually with a custom install!"; 1303 goto done; 1304 } 1305 1306 home_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1307 label_chunk_info[here].c, sz, part, 1308 FS_BSDFFS, CHUNK_AUTO_SIZE); 1309 if (!home_chunk) { 1310 msg = "Unable to create the /home partition. Not enough space?\n" 1311 "You will need to partition your disk manually with a custom install!"; 1312 goto done; 1313 } 1314 home_chunk->private_data = new_part("/home", TRUE, home_chunk->size); 1315 home_chunk->private_free = safe_free; 1316 home_chunk->flags |= CHUNK_NEWFS; 1317 record_label_chunks(devs, dev); 1318 } 1319 } 1320 1321 /* At this point, we're reasonably "labelled" */ 1322 if (variable_cmp(DISK_LABELLED, "written")) 1323 variable_set2(DISK_LABELLED, "yes", 0); 1324 1325done: 1326 if (msg) { 1327 if (root_chunk) 1328 Delete_Chunk(root_chunk->disk, root_chunk); 1329 if (swap_chunk) 1330 Delete_Chunk(swap_chunk->disk, swap_chunk); 1331 if (var_chunk) 1332 Delete_Chunk(var_chunk->disk, var_chunk); 1333 if (tmp_chunk) 1334 Delete_Chunk(tmp_chunk->disk, tmp_chunk); 1335 if (usr_chunk) 1336 Delete_Chunk(usr_chunk->disk, usr_chunk); 1337 if (home_chunk) 1338 Delete_Chunk(home_chunk->disk, home_chunk); 1339 record_label_chunks(devs, dev); 1340 } 1341 return(msg); 1342} 1343 1344static int 1345diskLabelNonInteractive(Device *dev) 1346{ 1347 char *cp; 1348 PartType type; 1349 PartInfo *p; 1350 u_long flags = 0; 1351 int i, status; 1352 Device **devs; 1353 Disk *d; 1354 1355 status = DITEM_SUCCESS; 1356 cp = variable_get(VAR_DISK); 1357 if (!cp) { 1358 msgConfirm("diskLabel: No disk selected - can't label automatically."); 1359 return DITEM_FAILURE; 1360 } 1361 devs = deviceFind(cp, DEVICE_TYPE_DISK); 1362 if (!devs) { 1363 msgConfirm("diskLabel: No disk device %s found!", cp); 1364 return DITEM_FAILURE; 1365 } 1366 if (dev) 1367 d = dev->private; 1368 else 1369 d = devs[0]->private; 1370#ifdef __alpha__ 1371 maybe_dedicate(d); 1372#endif 1373 record_label_chunks(devs, dev); 1374 for (i = 0; label_chunk_info[i].c; i++) { 1375 Chunk *c1 = label_chunk_info[i].c; 1376 1377 if (label_chunk_info[i].type == PART_SLICE) { 1378 char name[512]; 1379 int entries = 1; 1380 1381 while (entries) { 1382 snprintf(name, sizeof name, "%s-%d", c1->name, entries); 1383 if ((cp = variable_get(name)) != NULL) { 1384 int sz, soft = 0; 1385 char typ[10], mpoint[50]; 1386 1387 if (sscanf(cp, "%s %d %s %d", typ, &sz, mpoint, &soft) < 3) { 1388 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 1389 status = DITEM_FAILURE; 1390 continue; 1391 } 1392 else { 1393 Chunk *tmp; 1394 1395 if (!strcmp(typ, "swap")) { 1396 type = PART_SWAP; 1397 strcpy(mpoint, "SWAP"); 1398 } 1399 else { 1400 type = PART_FILESYSTEM; 1401 if (!strcmp(mpoint, "/")) 1402 flags |= CHUNK_IS_ROOT; 1403 else 1404 flags &= ~CHUNK_IS_ROOT; 1405 } 1406 if (!sz) 1407 sz = space_free(c1); 1408 if (sz > space_free(c1)) { 1409 msgConfirm("Not enough free space to create partition: %s", mpoint); 1410 status = DITEM_FAILURE; 1411 continue; 1412 } 1413 if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 1414 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 1415 msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 1416 status = DITEM_FAILURE; 1417 break; 1418 } 1419 else { 1420 tmp->private_data = new_part(mpoint, TRUE, sz); 1421 tmp->private_free = safe_free; 1422 ((PartInfo *)tmp->private_data)->soft = soft; 1423 status = DITEM_SUCCESS; 1424 } 1425 } 1426 entries++; 1427 } 1428 else { 1429 /* No more matches, leave the loop */ 1430 entries = 0; 1431 } 1432 } 1433 } 1434 else { 1435 /* Must be something we can set a mountpoint for */ 1436 cp = variable_get(c1->name); 1437 if (cp) { 1438 char mpoint[50], do_newfs[8]; 1439 Boolean newfs = FALSE; 1440 1441 do_newfs[0] = '\0'; 1442 if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 1443 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 1444 status = DITEM_FAILURE; 1445 continue; 1446 } 1447 newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 1448 if (c1->private_data) { 1449 p = c1->private_data; 1450 p->newfs = newfs; 1451 strcpy(p->mountpoint, mpoint); 1452 } 1453 else { 1454 c1->private_data = new_part(mpoint, newfs, 0); 1455 c1->private_free = safe_free; 1456 } 1457 if (!strcmp(mpoint, "/")) 1458 c1->flags |= CHUNK_IS_ROOT; 1459 else 1460 c1->flags &= ~CHUNK_IS_ROOT; 1461 } 1462 } 1463 } 1464 if (status == DITEM_SUCCESS) 1465 variable_set2(DISK_LABELLED, "yes", 0); 1466 return status; 1467} 1468