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