2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
10 * Jordan Hubbard. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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
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.
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
37 #include "sysinstall.h"
39 #include <sys/disklabel.h>
40 #include <sys/param.h>
41 #include <sys/sysctl.h>
44 * Everything to do with editing the contents of disk labels.
47 /* A nice message we use a lot in the disklabel editor */
48 #define MSG_NOT_APPLICABLE "That option is not applicable here"
50 /* Where to start printing the freebsd slices */
51 #define CHUNK_SLICE_START_ROW 2
52 #define CHUNK_PART_START_ROW 11
54 /* The smallest filesystem we're willing to create */
55 #define FS_MIN_SIZE ONE_MEG
57 /* The smallest root filesystem we're willing to create */
59 #define ROOT_MIN_SIZE 40
61 #define ROOT_MIN_SIZE 30
64 /* The default root filesystem size */
66 #define ROOT_DEFAULT_SIZE 60
68 #define ROOT_DEFAULT_SIZE 40
71 /* The smallest swap partition we want to create by default */
72 #define SWAP_MIN_SIZE 16
74 /* The smallest /usr partition we're willing to create by default */
75 #define USR_MIN_SIZE 80
77 /* The smallest /var partition we're willing to create by default */
78 #define VAR_MIN_SIZE 20
80 /* The bottom-most row we're allowed to scribble on */
81 #define CHUNK_ROW_MAX 16
84 /* All the chunks currently displayed on the screen */
88 } label_chunk_info[MAX_CHUNKS + 1];
91 /*** with this value we try to track the most recently added label ***/
92 static int label_focus = 0, pslice_focus = 0;
94 static int diskLabel(Device *dev);
95 static int diskLabelNonInteractive(Device *dev);
98 labelHook(dialogMenuItem *selected)
100 Device **devs = NULL;
102 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
104 msgConfirm("Unable to find disk %s!", selected->prompt);
105 return DITEM_FAILURE;
107 /* Toggle enabled status? */
108 if (!devs[0]->enabled) {
109 devs[0]->enabled = TRUE;
113 devs[0]->enabled = FALSE;
114 return DITEM_SUCCESS | DITEM_RESTORE;
118 labelCheck(dialogMenuItem *selected)
120 Device **devs = NULL;
122 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
123 if (!devs || devs[0]->enabled == FALSE)
129 diskLabelEditor(dialogMenuItem *self)
136 cnt = diskGetSelectCount(&devs);
138 msgConfirm("No disks found! Please verify that your disk controller is being\n"
139 "properly probed at boot time. See the Hardware Guide on the\n"
140 "Documentation menu for clues on diagnosing this type of problem.");
141 return DITEM_FAILURE;
144 /* Some are already selected */
145 if (variable_get(VAR_NONINTERACTIVE))
146 i = diskLabelNonInteractive(NULL);
151 /* No disks are selected, fall-back case now */
152 cnt = deviceCount(devs);
154 devs[0]->enabled = TRUE;
155 if (variable_get(VAR_NONINTERACTIVE))
156 i = diskLabelNonInteractive(devs[0]);
158 i = diskLabel(devs[0]);
161 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck);
163 msgConfirm("No devices suitable for installation found!\n\n"
164 "Please verify that your disk controller (and attached drives)\n"
165 "were detected properly. This can be done by pressing the\n"
166 "[Scroll Lock] key and using the Arrow keys to move back to\n"
167 "the boot messages. Press [Scroll Lock] again to return.");
171 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE;
177 if (DITEM_STATUS(i) != DITEM_FAILURE) {
180 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
181 variable_set2(DISK_LABELLED, "yes", 0);
187 diskLabelCommit(dialogMenuItem *self)
193 if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes"))
196 msgConfirm("You must assign disk labels before this option can be used.");
199 /* The routine will guard against redundant writes, just as this one does */
200 else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS)
202 else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS)
205 msgInfo("All filesystem information written successfully.");
206 variable_set2(DISK_LABELLED, "written", 0);
212 /* See if we're already using a desired partition name */
214 check_conflict(char *name)
218 for (i = 0; label_chunk_info[i].c; i++)
219 if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)
220 && label_chunk_info[i].c->private_data
221 && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name))
226 /* How much space is in this FreeBSD slice? */
228 space_free(struct chunk *c)
233 for (c1 = c->part; c1; c1 = c1->next) {
234 if (c1->type != unused)
238 msgFatal("Partitions are larger than actual chunk??");
242 /* Snapshot the current situation into the displayed chunks structure */
244 record_label_chunks(Device **devs, Device *dev)
247 struct chunk *c1, *c2;
251 /* First buzz through and pick up the FreeBSD slices */
252 for (i = 0; devs[i]; i++) {
253 if ((dev && devs[i] != dev) || !devs[i]->enabled)
255 d = (Disk *)devs[i]->private;
257 msgFatal("No chunk list found for %s!", d->name);
259 /* Put the slice entries first */
260 for (c1 = d->chunks->part; c1; c1 = c1->next) {
261 if (c1->type == freebsd) {
262 label_chunk_info[j].type = PART_SLICE;
263 label_chunk_info[j].c = c1;
269 /* Now run through again and get the FreeBSD partition entries */
270 for (i = 0; devs[i]; i++) {
271 if (!devs[i]->enabled)
273 d = (Disk *)devs[i]->private;
274 /* Then buzz through and pick up the partitions */
275 for (c1 = d->chunks->part; c1; c1 = c1->next) {
276 if (c1->type == freebsd) {
277 for (c2 = c1->part; c2; c2 = c2->next) {
278 if (c2->type == part) {
279 if (c2->subtype == FS_SWAP)
280 label_chunk_info[j].type = PART_SWAP;
282 label_chunk_info[j].type = PART_FILESYSTEM;
283 label_chunk_info[j].c = c2;
288 else if (c1->type == fat) {
289 label_chunk_info[j].type = PART_FAT;
290 label_chunk_info[j].c = c1;
295 label_chunk_info[j].c = NULL;
297 here = j ? j - 1 : 0;
301 /* A new partition entry */
303 new_part(char *mpoint, Boolean newfs, u_long size)
308 mpoint = "/change_me";
310 ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
311 sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
312 strcpy(ret->newfs_cmd, "newfs ");
313 strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS));
320 /* Get the mountpoint for a partition and save it away */
322 get_mountpoint(struct chunk *old)
327 if (old && old->private_data)
328 tmp = old->private_data;
335 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition");
336 DialogX = DialogY = 0;
341 free(old->private_data);
342 old->private_data = NULL;
347 /* Is it just the same value? */
348 if (tmp && !strcmp(tmp->mountpoint, val))
351 /* Did we use it already? */
352 if (check_conflict(val)) {
353 msgConfirm("You already have a mount point for %s assigned!", val);
359 msgConfirm("Mount point must start with a / character");
363 /* Is it going to be mounted on root? */
364 if (!strcmp(val, "/")) {
366 old->flags |= CHUNK_IS_ROOT;
369 old->flags &= ~CHUNK_IS_ROOT;
372 val = string_skipwhite(string_prune(val));
373 tmp = new_part(val, TRUE, 0);
375 old->private_data = tmp;
376 old->private_free = safe_free;
381 /* Get the type of the new partiton */
383 get_partition_type(void)
388 static unsigned char *fs_types[] = {
396 i = dialog_menu("Please choose a partition type",
397 "If you want to use this partition for swap space, select Swap.\n"
398 "If you want to put a filesystem on it, choose FS.",
399 -1, -1, 2, 2, fs_types, selection, NULL, NULL);
400 DialogX = DialogY = 0;
402 if (!strcmp(selection, "FS"))
403 return PART_FILESYSTEM;
404 else if (!strcmp(selection, "Swap"))
410 /* If the user wants a special newfs command for this, set it */
412 getNewfsCmd(PartInfo *p)
416 val = msgGetInput(p->newfs_cmd,
417 "Please enter the newfs command and options you'd like to use in\n"
418 "creating this file system.");
420 sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
423 #define MAX_MOUNT_NAME 12
425 #define PART_PART_COL 0
426 #define PART_MOUNT_COL 8
427 #define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
428 #define PART_NEWFS_COL (PART_SIZE_COL + 8)
431 #define TOTAL_AVAIL_LINES (10)
432 #define PSLICE_SHOWABLE (4)
435 /* stick this all up on the screen */
437 print_label_chunks(void)
439 int i, j, srow, prow, pcol;
442 int ChunkPartStartRow;
445 /********************************************************/
446 /*** These values are for controling screen resources ***/
447 /*** Each label line holds up to 2 labels, so beware! ***/
448 /*** strategy will be to try to always make sure the ***/
449 /*** highlighted label is in the active display area. ***/
450 /********************************************************/
451 int pslice_max, label_max;
452 int pslice_count, label_count, label_focus_found, pslice_focus_found;
455 mvaddstr(0, 25, "FreeBSD Disklabel Editor");
458 /*** Count the number of parition slices ***/
460 for (i = 0; label_chunk_info[i].c ; i++) {
461 if (label_chunk_info[i].type == PART_SLICE)
464 pslice_max = pslice_count;
466 /*** 4 line max for partition slices ***/
467 if (pslice_max > PSLICE_SHOWABLE) {
468 pslice_max = PSLICE_SHOWABLE;
470 ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max;
472 /*** View partition slices modulo pslice_max ***/
473 label_max = TOTAL_AVAIL_LINES - pslice_max;
475 for (i = 0; i < 2; i++) {
476 mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part");
477 mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----");
479 mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount");
480 mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----");
482 mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size");
483 mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----");
485 mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs");
486 mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----");
488 srow = CHUNK_SLICE_START_ROW;
492 /*** these variables indicate that the focused item is shown currently ***/
493 label_focus_found = 0;
494 pslice_focus_found = 0;
498 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " ");
499 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " ");
501 ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0);
504 /*** wrefresh(ChunkWin); ***/
506 for (i = 0; label_chunk_info[i].c; i++) {
507 /* Is it a slice entry displayed at the top? */
508 if (label_chunk_info[i].type == PART_SLICE) {
509 /*** This causes the new pslice to replace the previous display ***/
510 /*** focus must remain on the most recently active pslice ***/
511 if (pslice_count == pslice_max) {
512 if (pslice_focus_found) {
513 /*** This is where we can mark the more following ***/
515 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***");
520 /*** this is where we set the more previous ***/
522 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***");
525 srow = CHUNK_SLICE_START_ROW;
529 sz = space_free(label_chunk_info[i].c);
531 attrset(ATTR_SELECTED);
532 if (i == pslice_focus)
533 pslice_focus_found = -1;
536 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
537 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name,
545 /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */
547 char onestr[PART_OFF], num[10], *mountpoint, *newfs;
550 * We copy this into a blank-padded string so that it looks like
551 * a solid bar in reverse-video
553 memset(onestr, ' ', PART_OFF - 1);
554 onestr[PART_OFF - 1] = '\0';
556 /*** Track how many labels have been displayed ***/
557 if (label_count == ((label_max - 1 ) * 2)) {
558 if (label_focus_found) {
568 /* Go for two columns if we've written one full columns worth */
569 /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/
570 if (label_count == label_max - 1) {
574 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name));
575 /* If it's a filesystem, display the mountpoint */
576 if (label_chunk_info[i].c->private_data
577 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT))
578 mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint;
579 else if (label_chunk_info[i].type == PART_SWAP)
582 mountpoint = "<none>";
584 /* Now display the newfs field */
585 if (label_chunk_info[i].type == PART_FAT)
587 else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM)
588 newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N";
589 else if (label_chunk_info[i].type == PART_SWAP)
593 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
594 onestr[PART_MOUNT_COL + j] = mountpoint[j];
595 snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0);
596 memcpy(onestr + PART_SIZE_COL, num, strlen(num));
597 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
598 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0';
599 if (i == label_focus) {
600 label_focus_found = -1;
601 wattrset(ChunkWin, A_BOLD);
604 wattrset(ChunkWin, ATTR_SELECTED);
606 /*** lazy man's way of padding this string ***/
607 while (strlen( onestr ) < 37)
610 mvwaddstr(ChunkWin, prow, pcol, onestr);
611 wattrset(ChunkWin, A_NORMAL);
618 /*** this will erase all the extra stuff ***/
619 memset(clrmsg, ' ', 37);
622 while (pslice_count < pslice_max) {
623 mvprintw(srow++, 0, clrmsg);
627 while (label_count < (2 * (label_max - 1))) {
628 mvwaddstr(ChunkWin, prow++, pcol, clrmsg);
630 if (prow == (label_max - 1)) {
640 print_command_summary(void)
642 mvprintw(17, 0, "The following commands are valid here (upper or lower case):");
643 mvprintw(18, 0, "C = Create D = Delete M = Mount pt.");
645 mvprintw(18, 49, "W = Write");
646 mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish");
647 mvprintw(20, 0, "A = Auto Defaults for all!");
648 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select.");
655 extern void print_label_chunks();
657 print_label_chunks();
663 * If there isn't a freebsd chunk already (i.e. there is no label),
667 maybe_dedicate(Disk* d)
671 for (c = d->chunks->part; c; c = c->next) {
672 if (c->type == freebsd)
677 msgDebug("dedicating disk");
685 diskLabel(Device *dev)
701 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
703 msgConfirm("No disks found!");
704 return DITEM_FAILURE;
707 keypad(stdscr, TRUE);
709 for (i = 0; devs[i]; i++) {
710 maybe_dedicate((Disk*) devs[i]->private);
713 record_label_chunks(devs, dev);
719 print_label_chunks();
720 print_command_summary();
722 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
734 switch (toupper(key)) {
736 static char _msg[40];
738 case '\014': /* ^L */
742 case '\020': /* ^P */
748 while (label_chunk_info[here + 1].c)
752 case '\016': /* ^N */
757 if (label_chunk_info[here + 1].c)
768 while (label_chunk_info[here + 1].c)
774 systemDisplayHelp("partition");
779 if (label_chunk_info[here].type != PART_SLICE) {
780 msg = "You can only do this in a disk slice (at top of screen)";
783 sz = space_free(label_chunk_info[here].c);
784 if (sz <= FS_MIN_SIZE)
785 msg = "Not enough free space to create a new partition in the slice";
792 Chunk *rootdev, *swapdev, *usrdev, *vardev;
794 (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev);
796 cp = variable_get(VAR_ROOT_SIZE);
797 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
798 (cp ? atoi(cp) : ROOT_DEFAULT_SIZE) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT);
800 msgConfirm("Unable to create the root partition. Too big?");
804 tmp->private_data = new_part("/", TRUE, tmp->size);
805 tmp->private_free = safe_free;
806 record_label_chunks(devs, dev);
810 cp = variable_get(VAR_SWAP_SIZE);
812 swsize = atoi(cp) * ONE_MEG;
816 size = sizeof physmem;
817 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0);
818 swsize = 16 * ONE_MEG + (physmem * 2 / 512);
820 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
821 swsize, part, FS_SWAP, 0);
823 msgConfirm("Unable to create the swap partition. Too big?");
827 tmp->private_data = 0;
828 tmp->private_free = safe_free;
829 record_label_chunks(devs, dev);
833 cp = variable_get(VAR_VAR_SIZE);
835 sz = atoi(cp) * ONE_MEG;
837 sz = variable_get(VAR_NO_USR)
838 ? space_free(label_chunk_info[here].c)
839 : VAR_MIN_SIZE * ONE_MEG;
841 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
842 sz, part, FS_BSDFFS, 0);
844 msgConfirm("Less than %dMB free for /var - you will need to\n"
845 "partition your disk manually with a custom install!",
846 (cp ? atoi(cp) : VAR_MIN_SIZE));
850 tmp->private_data = new_part("/var", TRUE, tmp->size);
851 tmp->private_free = safe_free;
852 record_label_chunks(devs, dev);
855 if (!usrdev && !variable_get(VAR_NO_USR)) {
856 cp = variable_get(VAR_USR_SIZE);
858 sz = atoi(cp) * ONE_MEG;
860 sz = space_free(label_chunk_info[here].c);
862 if (sz < (USR_MIN_SIZE * ONE_MEG)) {
863 msgConfirm("Less than %dMB free for /usr - you will need to\n"
864 "partition your disk manually with a custom install!", USR_MIN_SIZE);
869 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
870 label_chunk_info[here].c,
871 sz, part, FS_BSDFFS, 0);
873 msgConfirm("Unable to create the /usr partition. Not enough space?\n"
874 "You will need to partition your disk manually with a custom install!");
878 tmp->private_data = new_part("/usr", TRUE, tmp->size);
879 tmp->private_free = safe_free;
880 record_label_chunks(devs, dev);
884 /* At this point, we're reasonably "labelled" */
885 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
886 variable_set2(DISK_LABELLED, "yes", 0);
891 if (label_chunk_info[here].type != PART_SLICE) {
892 msg = "You can only do this in a master partition (see top of screen)";
895 sz = space_free(label_chunk_info[here].c);
896 if (sz <= FS_MIN_SIZE) {
897 msg = "Not enough space to create an additional FreeBSD partition";
907 sprintf(osize, "%d", sz);
910 val = msgGetInput(osize,
911 "Please specify the partition size in blocks or append a trailing M for\n"
912 "megabytes or C for cylinders. %d blocks (%dMB) are free.",
914 DialogX = DialogY = 0;
915 if (!val || (size = strtol(val, &cp, 0)) <= 0) {
921 if (toupper(*cp) == 'M')
923 else if (toupper(*cp) == 'C')
924 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect);
926 if (size <= FS_MIN_SIZE) {
927 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG);
931 type = get_partition_type();
932 if (type == PART_NONE) {
938 if (type == PART_FILESYSTEM) {
939 if ((p = get_mountpoint(NULL)) == NULL) {
944 else if (!strcmp(p->mountpoint, "/"))
945 flags |= CHUNK_IS_ROOT;
947 flags &= ~CHUNK_IS_ROOT;
952 if ((flags & CHUNK_IS_ROOT)) {
953 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) {
954 msgConfirm("This region cannot be used for your root partition as the\n"
955 "FreeBSD boot code cannot deal with a root partition created\n"
956 "in that location. Please choose another location or smaller\n"
957 "size for your root partition and try again!");
961 if (size < (ROOT_MIN_SIZE * ONE_MEG)) {
962 msgConfirm("Warning: This is smaller than the recommended size for a\n"
963 "root partition. For a variety of reasons, root\n"
964 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE);
967 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
968 label_chunk_info[here].c,
970 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS,
973 msgConfirm("Unable to create the partition. Too big?");
977 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
978 msgConfirm("This region cannot be used for your root partition as it starts\n"
979 "or extends past the 1024'th cylinder mark and is thus a\n"
980 "poor location to boot from. Please choose another\n"
981 "location (or smaller size) for your root partition and try again!");
982 Delete_Chunk(label_chunk_info[here].c->disk, tmp);
986 if (type != PART_SWAP) {
987 /* This is needed to tell the newfs -u about the size */
988 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size);
992 tmp->private_data = p;
993 tmp->private_free = safe_free;
994 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
995 variable_set2(DISK_LABELLED, "yes", 0);
996 record_label_chunks(devs, dev);
998 /*** This is where we assign focus to new label so it shows ***/
1002 for (i = 0; label_chunk_info[i].c; ++i) {
1003 if (label_chunk_info[i].c == tmp) {
1008 if (label_focus == -1)
1009 label_focus = i - 1;
1015 case 'D': /* delete */
1016 if (label_chunk_info[here].type == PART_SLICE) {
1017 msg = MSG_NOT_APPLICABLE;
1020 else if (label_chunk_info[here].type == PART_FAT) {
1021 msg = "Use the Disk Partition Editor to delete DOS partitions";
1024 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c);
1025 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1026 variable_set2(DISK_LABELLED, "yes", 0);
1027 record_label_chunks(devs, dev);
1030 case 'M': /* mount */
1031 switch(label_chunk_info[here].type) {
1033 msg = MSG_NOT_APPLICABLE;
1037 msg = "You don't need to specify a mountpoint for a swap partition.";
1041 case PART_FILESYSTEM:
1042 oldp = label_chunk_info[here].c->private_data;
1043 p = get_mountpoint(label_chunk_info[here].c);
1047 if (label_chunk_info[here].type == PART_FAT
1048 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr")
1049 || !strcmp(p->mountpoint, "/var"))) {
1050 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint);
1051 strcpy(p->mountpoint, "/bogus");
1054 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1055 variable_set2(DISK_LABELLED, "yes", 0);
1056 record_label_chunks(devs, dev);
1061 msgFatal("Bogus partition under cursor???");
1066 case 'N': /* Set newfs options */
1067 if (label_chunk_info[here].c->private_data &&
1068 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs)
1069 getNewfsCmd(label_chunk_info[here].c->private_data);
1071 msg = MSG_NOT_APPLICABLE;
1075 case 'T': /* Toggle newfs state */
1076 if (label_chunk_info[here].type == PART_FILESYSTEM) {
1077 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
1078 label_chunk_info[here].c->private_data =
1079 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size);
1081 label_chunk_info[here].c->private_free = safe_free;
1082 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1083 variable_set2(DISK_LABELLED, "yes", 0);
1086 msg = MSG_NOT_APPLICABLE;
1091 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) {
1092 msgConfirm("You've already written out your changes -\n"
1093 "it's too late to undo!");
1095 else if (!msgYesNo("Are you SURE you want to Undo everything?")) {
1096 variable_unset(DISK_PARTITIONED);
1097 variable_unset(DISK_LABELLED);
1098 for (i = 0; devs[i]; i++) {
1101 if (!devs[i]->enabled)
1103 else if ((d = Open_Disk(devs[i]->name)) != NULL) {
1104 Free_Disk(devs[i]->private);
1105 devs[i]->private = d;
1106 diskPartition(devs[i]);
1109 record_label_chunks(devs, dev);
1115 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) {
1116 msgConfirm("You've already written out your changes - if you\n"
1117 "wish to overwrite them, you'll have to start this\n"
1118 "procedure again from the beginning.");
1120 else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n"
1121 "installation. If you are installing FreeBSD for the first time\n"
1122 "then you should simply type Q when you're finished here and your\n"
1123 "changes will be committed in one batch automatically at the end of\n"
1124 "these questions.\n\n"
1125 "Are you absolutely sure you want to do this now?")) {
1126 variable_set2(DISK_LABELLED, "yes", 0);
1127 diskLabelCommit(NULL);
1133 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n"
1134 "This is an entirely undocumented feature which you are not\n"
1135 "expected to understand!")) {
1141 DialogActive = FALSE;
1142 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
1144 msgConfirm("Can't find any disk devices!");
1147 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) {
1148 if (devs[i]->enabled)
1149 slice_wizard(((Disk *)devs[i]->private));
1151 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1152 variable_set2(DISK_LABELLED, "yes", 0);
1153 DialogActive = TRUE;
1154 record_label_chunks(devs, dev);
1158 msg = "A most prudent choice!";
1161 case '\033': /* ESC */
1168 sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key);
1172 if (label_chunk_info[here].type == PART_SLICE)
1173 pslice_focus = here;
1177 return DITEM_SUCCESS | DITEM_RESTORE;
1181 diskLabelNonInteractive(Device *dev)
1191 status = DITEM_SUCCESS;
1193 cp = variable_get(VAR_DISK);
1196 msgConfirm("diskLabel: No disk selected - can't label automatically.");
1197 return DITEM_FAILURE;
1199 devs = deviceFind(cp, DEVICE_TYPE_DISK);
1201 msgConfirm("diskLabel: No disk device %s found!", cp);
1202 return DITEM_FAILURE;
1207 d = devs[0]->private;
1211 record_label_chunks(devs, dev);
1212 for (i = 0; label_chunk_info[i].c; i++) {
1213 Chunk *c1 = label_chunk_info[i].c;
1215 if (label_chunk_info[i].type == PART_SLICE) {
1220 snprintf(name, sizeof name, "%s-%d", c1->name, entries);
1221 if ((cp = variable_get(name)) != NULL) {
1223 char typ[10], mpoint[50];
1225 if (sscanf(cp, "%s %d %s", typ, &sz, mpoint) != 3) {
1226 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp);
1227 status = DITEM_FAILURE;
1233 if (!strcmp(typ, "swap")) {
1235 strcpy(mpoint, "SWAP");
1238 type = PART_FILESYSTEM;
1239 if (!strcmp(mpoint, "/"))
1240 flags |= CHUNK_IS_ROOT;
1242 flags &= ~CHUNK_IS_ROOT;
1245 sz = space_free(c1);
1246 if (sz > space_free(c1)) {
1247 msgConfirm("Not enough free space to create partition: %s", mpoint);
1248 status = DITEM_FAILURE;
1251 if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part,
1252 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) {
1253 msgConfirm("Unable to create from partition spec: %s. Too big?", cp);
1254 status = DITEM_FAILURE;
1258 tmp->private_data = new_part(mpoint, TRUE, sz);
1259 tmp->private_free = safe_free;
1260 status = DITEM_SUCCESS;
1266 /* No more matches, leave the loop */
1272 /* Must be something we can set a mountpoint for */
1273 cp = variable_get(c1->name);
1275 char mpoint[50], do_newfs[8];
1276 Boolean newfs = FALSE;
1279 if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) {
1281 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp);
1282 status = DITEM_FAILURE;
1285 newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE;
1286 if (c1->private_data) {
1287 p = c1->private_data;
1289 strcpy(p->mountpoint, mpoint);
1292 c1->private_data = new_part(mpoint, newfs, 0);
1293 c1->private_free = safe_free;
1295 if (!strcmp(mpoint, "/"))
1296 c1->flags |= CHUNK_IS_ROOT;
1298 c1->flags &= ~CHUNK_IS_ROOT;
1302 if (status == DITEM_SUCCESS)
1303 variable_set2(DISK_LABELLED, "yes", 0);