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 70
68 #define ROOT_DEFAULT_SIZE 50
71 /* The smallest swap partition we want to create by default */
72 #define SWAP_MIN_SIZE 32
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;
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;
176 if (DITEM_STATUS(i) != DITEM_FAILURE) {
179 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
180 variable_set2(DISK_LABELLED, "yes", 0);
186 diskLabelCommit(dialogMenuItem *self)
192 if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes"))
195 msgConfirm("You must assign disk labels before this option can be used.");
198 /* The routine will guard against redundant writes, just as this one does */
199 else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS)
201 else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS)
204 msgInfo("All filesystem information written successfully.");
205 variable_set2(DISK_LABELLED, "written", 0);
211 /* See if we're already using a desired partition name */
213 check_conflict(char *name)
217 for (i = 0; label_chunk_info[i].c; i++)
218 if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)
219 && label_chunk_info[i].c->private_data
220 && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name))
225 /* How much space is in this FreeBSD slice? */
227 space_free(struct chunk *c)
232 for (c1 = c->part; c1; c1 = c1->next) {
233 if (c1->type != unused)
237 msgFatal("Partitions are larger than actual chunk??");
241 /* Snapshot the current situation into the displayed chunks structure */
243 record_label_chunks(Device **devs, Device *dev)
246 struct chunk *c1, *c2;
250 /* First buzz through and pick up the FreeBSD slices */
251 for (i = 0; devs[i]; i++) {
252 if ((dev && devs[i] != dev) || !devs[i]->enabled)
254 d = (Disk *)devs[i]->private;
256 msgFatal("No chunk list found for %s!", d->name);
258 /* Put the slice entries first */
259 for (c1 = d->chunks->part; c1; c1 = c1->next) {
260 if (c1->type == freebsd) {
261 label_chunk_info[j].type = PART_SLICE;
262 label_chunk_info[j].c = c1;
268 /* Now run through again and get the FreeBSD partition entries */
269 for (i = 0; devs[i]; i++) {
270 if (!devs[i]->enabled)
272 d = (Disk *)devs[i]->private;
273 /* Then buzz through and pick up the partitions */
274 for (c1 = d->chunks->part; c1; c1 = c1->next) {
275 if (c1->type == freebsd) {
276 for (c2 = c1->part; c2; c2 = c2->next) {
277 if (c2->type == part) {
278 if (c2->subtype == FS_SWAP)
279 label_chunk_info[j].type = PART_SWAP;
281 label_chunk_info[j].type = PART_FILESYSTEM;
282 label_chunk_info[j].c = c2;
287 else if (c1->type == fat) {
288 label_chunk_info[j].type = PART_FAT;
289 label_chunk_info[j].c = c1;
294 label_chunk_info[j].c = NULL;
296 here = j ? j - 1 : 0;
300 /* A new partition entry */
302 new_part(char *mpoint, Boolean newfs, u_long size)
307 mpoint = "/change_me";
309 ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
310 sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
311 strcpy(ret->newfs_cmd, "newfs ");
312 strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS));
319 /* Get the mountpoint for a partition and save it away */
321 get_mountpoint(struct chunk *old)
326 if (old && old->private_data)
327 tmp = old->private_data;
330 val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition");
335 free(old->private_data);
336 old->private_data = NULL;
341 /* Is it just the same value? */
342 if (tmp && !strcmp(tmp->mountpoint, val))
345 /* Did we use it already? */
346 if (check_conflict(val)) {
347 msgConfirm("You already have a mount point for %s assigned!", val);
353 msgConfirm("Mount point must start with a / character");
357 /* Is it going to be mounted on root? */
358 if (!strcmp(val, "/")) {
360 old->flags |= CHUNK_IS_ROOT;
363 old->flags &= ~CHUNK_IS_ROOT;
366 val = string_skipwhite(string_prune(val));
367 tmp = new_part(val, TRUE, 0);
369 old->private_data = tmp;
370 old->private_free = safe_free;
375 /* Get the type of the new partiton */
377 get_partition_type(void)
381 static unsigned char *fs_types[] = {
387 WINDOW *w = savescr();
389 i = dialog_menu("Please choose a partition type",
390 "If you want to use this partition for swap space, select Swap.\n"
391 "If you want to put a filesystem on it, choose FS.",
392 -1, -1, 2, 2, fs_types, selection, NULL, NULL);
395 if (!strcmp(selection, "FS"))
396 return PART_FILESYSTEM;
397 else if (!strcmp(selection, "Swap"))
403 /* If the user wants a special newfs command for this, set it */
405 getNewfsCmd(PartInfo *p)
409 val = msgGetInput(p->newfs_cmd,
410 "Please enter the newfs command and options you'd like to use in\n"
411 "creating this file system.");
413 sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
416 #define MAX_MOUNT_NAME 10
418 #define PART_PART_COL 0
419 #define PART_MOUNT_COL 10
420 #define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
421 #define PART_NEWFS_COL (PART_SIZE_COL + 8)
424 #define TOTAL_AVAIL_LINES (10)
425 #define PSLICE_SHOWABLE (4)
428 /* stick this all up on the screen */
430 print_label_chunks(void)
432 int i, j, srow, prow, pcol;
435 int ChunkPartStartRow;
438 /********************************************************/
439 /*** These values are for controling screen resources ***/
440 /*** Each label line holds up to 2 labels, so beware! ***/
441 /*** strategy will be to try to always make sure the ***/
442 /*** highlighted label is in the active display area. ***/
443 /********************************************************/
444 int pslice_max, label_max;
445 int pslice_count, label_count, label_focus_found, pslice_focus_found;
448 mvaddstr(0, 25, "FreeBSD Disklabel Editor");
451 /*** Count the number of parition slices ***/
453 for (i = 0; label_chunk_info[i].c ; i++) {
454 if (label_chunk_info[i].type == PART_SLICE)
457 pslice_max = pslice_count;
459 /*** 4 line max for partition slices ***/
460 if (pslice_max > PSLICE_SHOWABLE) {
461 pslice_max = PSLICE_SHOWABLE;
463 ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max;
465 /*** View partition slices modulo pslice_max ***/
466 label_max = TOTAL_AVAIL_LINES - pslice_max;
468 for (i = 0; i < 2; i++) {
469 mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part");
470 mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----");
472 mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount");
473 mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----");
475 mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size");
476 mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----");
478 mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs");
479 mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----");
481 srow = CHUNK_SLICE_START_ROW;
485 /*** these variables indicate that the focused item is shown currently ***/
486 label_focus_found = 0;
487 pslice_focus_found = 0;
491 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " ");
492 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " ");
494 ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0);
497 /*** wrefresh(ChunkWin); ***/
499 for (i = 0; label_chunk_info[i].c; i++) {
500 /* Is it a slice entry displayed at the top? */
501 if (label_chunk_info[i].type == PART_SLICE) {
502 /*** This causes the new pslice to replace the previous display ***/
503 /*** focus must remain on the most recently active pslice ***/
504 if (pslice_count == pslice_max) {
505 if (pslice_focus_found) {
506 /*** This is where we can mark the more following ***/
508 mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***");
513 /*** this is where we set the more previous ***/
515 mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***");
518 srow = CHUNK_SLICE_START_ROW;
522 sz = space_free(label_chunk_info[i].c);
524 attrset(ATTR_SELECTED);
525 if (i == pslice_focus)
526 pslice_focus_found = -1;
529 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
530 label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name,
538 /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */
540 char onestr[PART_OFF], num[10], *mountpoint, *newfs;
543 * We copy this into a blank-padded string so that it looks like
544 * a solid bar in reverse-video
546 memset(onestr, ' ', PART_OFF - 1);
547 onestr[PART_OFF - 1] = '\0';
549 /*** Track how many labels have been displayed ***/
550 if (label_count == ((label_max - 1 ) * 2)) {
551 if (label_focus_found) {
561 /* Go for two columns if we've written one full columns worth */
562 /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/
563 if (label_count == label_max - 1) {
567 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name));
568 /* If it's a filesystem, display the mountpoint */
569 if (label_chunk_info[i].c->private_data
570 && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT))
571 mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint;
572 else if (label_chunk_info[i].type == PART_SWAP)
575 mountpoint = "<none>";
577 /* Now display the newfs field */
578 if (label_chunk_info[i].type == PART_FAT)
580 else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM)
581 newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N";
582 else if (label_chunk_info[i].type == PART_SWAP)
586 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
587 onestr[PART_MOUNT_COL + j] = mountpoint[j];
588 snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0);
589 memcpy(onestr + PART_SIZE_COL, num, strlen(num));
590 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
591 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0';
592 if (i == label_focus) {
593 label_focus_found = -1;
594 wattrset(ChunkWin, A_BOLD);
597 wattrset(ChunkWin, ATTR_SELECTED);
599 /*** lazy man's way of padding this string ***/
600 while (strlen( onestr ) < 37)
603 mvwaddstr(ChunkWin, prow, pcol, onestr);
604 wattrset(ChunkWin, A_NORMAL);
611 /*** this will erase all the extra stuff ***/
612 memset(clrmsg, ' ', 37);
615 while (pslice_count < pslice_max) {
616 mvprintw(srow++, 0, clrmsg);
620 while (label_count < (2 * (label_max - 1))) {
621 mvwaddstr(ChunkWin, prow++, pcol, clrmsg);
623 if (prow == (label_max - 1)) {
633 print_command_summary(void)
635 mvprintw(17, 0, "The following commands are valid here (upper or lower case):");
636 mvprintw(18, 0, "C = Create D = Delete M = Mount pt.");
638 mvprintw(18, 49, "W = Write");
639 mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish");
640 mvprintw(20, 0, "A = Auto Defaults for all!");
641 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select.");
648 extern void print_label_chunks();
650 print_label_chunks();
656 * If there isn't a freebsd chunk already (i.e. there is no label),
660 maybe_dedicate(Disk* d)
664 for (c = d->chunks->part; c; c = c->next) {
665 if (c->type == freebsd)
670 msgDebug("dedicating disk");
678 diskLabel(Device *dev)
689 WINDOW *w = savescr();
695 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
697 msgConfirm("No disks found!");
699 return DITEM_FAILURE;
702 keypad(stdscr, TRUE);
704 for (i = 0; devs[i]; i++) {
705 maybe_dedicate((Disk*) devs[i]->private);
708 record_label_chunks(devs, dev);
714 print_label_chunks();
715 print_command_summary();
717 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
729 switch (toupper(key)) {
731 static char _msg[40];
733 case '\014': /* ^L */
737 case '\020': /* ^P */
743 while (label_chunk_info[here + 1].c)
747 case '\016': /* ^N */
752 if (label_chunk_info[here + 1].c)
763 while (label_chunk_info[here + 1].c)
769 systemDisplayHelp("partition");
774 if (label_chunk_info[here].type != PART_SLICE) {
775 msg = "You can only do this in a disk slice (at top of screen)";
778 sz = space_free(label_chunk_info[here].c);
779 if (sz <= FS_MIN_SIZE)
780 msg = "Not enough free space to create a new partition in the slice";
787 Chunk *rootdev, *swapdev, *usrdev, *vardev;
789 (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev);
791 cp = variable_get(VAR_ROOT_SIZE);
792 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
793 (cp ? atoi(cp) : ROOT_DEFAULT_SIZE) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT);
795 msgConfirm("Unable to create the root partition. Too big?");
799 tmp->private_data = new_part("/", TRUE, tmp->size);
800 tmp->private_free = safe_free;
801 record_label_chunks(devs, dev);
805 cp = variable_get(VAR_SWAP_SIZE);
807 swsize = atoi(cp) * ONE_MEG;
811 size = sizeof physmem;
812 sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0);
813 swsize = 16 * ONE_MEG + (physmem * 2 / 512);
815 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
816 swsize, part, FS_SWAP, 0);
818 msgConfirm("Unable to create the swap partition. Too big?");
822 tmp->private_data = 0;
823 tmp->private_free = safe_free;
824 record_label_chunks(devs, dev);
828 cp = variable_get(VAR_VAR_SIZE);
830 sz = atoi(cp) * ONE_MEG;
832 sz = variable_get(VAR_NO_USR)
833 ? space_free(label_chunk_info[here].c)
834 : VAR_MIN_SIZE * ONE_MEG;
836 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
837 sz, part, FS_BSDFFS, 0);
839 msgConfirm("Less than %dMB free for /var - you will need to\n"
840 "partition your disk manually with a custom install!",
841 (cp ? atoi(cp) : VAR_MIN_SIZE));
845 tmp->private_data = new_part("/var", TRUE, tmp->size);
846 tmp->private_free = safe_free;
847 record_label_chunks(devs, dev);
850 if (!usrdev && !variable_get(VAR_NO_USR)) {
851 cp = variable_get(VAR_USR_SIZE);
853 sz = atoi(cp) * ONE_MEG;
855 sz = space_free(label_chunk_info[here].c);
857 if (sz < (USR_MIN_SIZE * ONE_MEG)) {
858 msgConfirm("Less than %dMB free for /usr - you will need to\n"
859 "partition your disk manually with a custom install!", USR_MIN_SIZE);
864 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
865 label_chunk_info[here].c,
866 sz, part, FS_BSDFFS, 0);
868 msgConfirm("Unable to create the /usr partition. Not enough space?\n"
869 "You will need to partition your disk manually with a custom install!");
873 tmp->private_data = new_part("/usr", TRUE, tmp->size);
874 tmp->private_free = safe_free;
875 record_label_chunks(devs, dev);
879 /* At this point, we're reasonably "labelled" */
880 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
881 variable_set2(DISK_LABELLED, "yes", 0);
886 if (label_chunk_info[here].type != PART_SLICE) {
887 msg = "You can only do this in a master partition (see top of screen)";
890 sz = space_free(label_chunk_info[here].c);
891 if (sz <= FS_MIN_SIZE) {
892 msg = "Not enough space to create an additional FreeBSD partition";
902 sprintf(osize, "%d", sz);
903 val = msgGetInput(osize,
904 "Please specify the partition size in blocks or append a trailing M for\n"
905 "megabytes or C for cylinders. %d blocks (%dMB) are free.",
907 if (!val || (size = strtol(val, &cp, 0)) <= 0) {
913 if (toupper(*cp) == 'M')
915 else if (toupper(*cp) == 'C')
916 size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect);
918 if (size <= FS_MIN_SIZE) {
919 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG);
923 type = get_partition_type();
924 if (type == PART_NONE) {
930 if (type == PART_FILESYSTEM) {
931 if ((p = get_mountpoint(NULL)) == NULL) {
936 else if (!strcmp(p->mountpoint, "/"))
937 flags |= CHUNK_IS_ROOT;
939 flags &= ~CHUNK_IS_ROOT;
944 if ((flags & CHUNK_IS_ROOT)) {
945 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) {
946 msgConfirm("This region cannot be used for your root partition as the\n"
947 "FreeBSD boot code cannot deal with a root partition created\n"
948 "in that location. Please choose another location or smaller\n"
949 "size for your root partition and try again!");
953 if (size < (ROOT_MIN_SIZE * ONE_MEG)) {
954 msgConfirm("Warning: This is smaller than the recommended size for a\n"
955 "root partition. For a variety of reasons, root\n"
956 "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE);
959 tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
960 label_chunk_info[here].c,
962 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS,
965 msgConfirm("Unable to create the partition. Too big?");
969 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
970 msgConfirm("This region cannot be used for your root partition as it starts\n"
971 "or extends past the 1024'th cylinder mark and is thus a\n"
972 "poor location to boot from. Please choose another\n"
973 "location (or smaller size) for your root partition and try again!");
974 Delete_Chunk(label_chunk_info[here].c->disk, tmp);
978 if (type != PART_SWAP) {
979 /* This is needed to tell the newfs -u about the size */
980 tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size);
984 tmp->private_data = p;
985 tmp->private_free = safe_free;
986 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
987 variable_set2(DISK_LABELLED, "yes", 0);
988 record_label_chunks(devs, dev);
990 /*** This is where we assign focus to new label so it shows ***/
994 for (i = 0; label_chunk_info[i].c; ++i) {
995 if (label_chunk_info[i].c == tmp) {
1000 if (label_focus == -1)
1001 label_focus = i - 1;
1007 case 'D': /* delete */
1008 if (label_chunk_info[here].type == PART_SLICE) {
1009 msg = MSG_NOT_APPLICABLE;
1012 else if (label_chunk_info[here].type == PART_FAT) {
1013 msg = "Use the Disk Partition Editor to delete DOS partitions";
1016 Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c);
1017 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1018 variable_set2(DISK_LABELLED, "yes", 0);
1019 record_label_chunks(devs, dev);
1022 case 'M': /* mount */
1023 switch(label_chunk_info[here].type) {
1025 msg = MSG_NOT_APPLICABLE;
1029 msg = "You don't need to specify a mountpoint for a swap partition.";
1033 case PART_FILESYSTEM:
1034 oldp = label_chunk_info[here].c->private_data;
1035 p = get_mountpoint(label_chunk_info[here].c);
1039 if (label_chunk_info[here].type == PART_FAT
1040 && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr")
1041 || !strcmp(p->mountpoint, "/var"))) {
1042 msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint);
1043 strcpy(p->mountpoint, "/bogus");
1046 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1047 variable_set2(DISK_LABELLED, "yes", 0);
1048 record_label_chunks(devs, dev);
1053 msgFatal("Bogus partition under cursor???");
1058 case 'N': /* Set newfs options */
1059 if (label_chunk_info[here].c->private_data &&
1060 ((PartInfo *)label_chunk_info[here].c->private_data)->newfs)
1061 getNewfsCmd(label_chunk_info[here].c->private_data);
1063 msg = MSG_NOT_APPLICABLE;
1067 case 'T': /* Toggle newfs state */
1068 if (label_chunk_info[here].type == PART_FILESYSTEM) {
1069 PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
1070 label_chunk_info[here].c->private_data =
1071 new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size);
1073 label_chunk_info[here].c->private_free = safe_free;
1074 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1075 variable_set2(DISK_LABELLED, "yes", 0);
1078 msg = MSG_NOT_APPLICABLE;
1083 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) {
1084 msgConfirm("You've already written out your changes -\n"
1085 "it's too late to undo!");
1087 else if (!msgYesNo("Are you SURE you want to Undo everything?")) {
1088 variable_unset(DISK_PARTITIONED);
1089 variable_unset(DISK_LABELLED);
1090 for (i = 0; devs[i]; i++) {
1093 if (!devs[i]->enabled)
1095 else if ((d = Open_Disk(devs[i]->name)) != NULL) {
1096 Free_Disk(devs[i]->private);
1097 devs[i]->private = d;
1098 diskPartition(devs[i]);
1101 record_label_chunks(devs, dev);
1107 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) {
1108 msgConfirm("You've already written out your changes - if you\n"
1109 "wish to overwrite them, you'll have to start this\n"
1110 "procedure again from the beginning.");
1112 else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n"
1113 "installation. If you are installing FreeBSD for the first time\n"
1114 "then you should simply type Q when you're finished here and your\n"
1115 "changes will be committed in one batch automatically at the end of\n"
1116 "these questions.\n\n"
1117 "Are you absolutely sure you want to do this now?")) {
1118 variable_set2(DISK_LABELLED, "yes", 0);
1119 diskLabelCommit(NULL);
1125 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n"
1126 "This is an entirely undocumented feature which you are not\n"
1127 "expected to understand!")) {
1133 DialogActive = FALSE;
1134 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
1136 msgConfirm("Can't find any disk devices!");
1139 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) {
1140 if (devs[i]->enabled)
1141 slice_wizard(((Disk *)devs[i]->private));
1143 if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written")))
1144 variable_set2(DISK_LABELLED, "yes", 0);
1145 DialogActive = TRUE;
1146 record_label_chunks(devs, dev);
1150 msg = "A most prudent choice!";
1153 case '\033': /* ESC */
1160 sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key);
1164 if (label_chunk_info[here].type == PART_SLICE)
1165 pslice_focus = here;
1170 return DITEM_SUCCESS;
1174 diskLabelNonInteractive(Device *dev)
1184 status = DITEM_SUCCESS;
1185 cp = variable_get(VAR_DISK);
1187 msgConfirm("diskLabel: No disk selected - can't label automatically.");
1188 return DITEM_FAILURE;
1190 devs = deviceFind(cp, DEVICE_TYPE_DISK);
1192 msgConfirm("diskLabel: No disk device %s found!", cp);
1193 return DITEM_FAILURE;
1198 d = devs[0]->private;
1202 record_label_chunks(devs, dev);
1203 for (i = 0; label_chunk_info[i].c; i++) {
1204 Chunk *c1 = label_chunk_info[i].c;
1206 if (label_chunk_info[i].type == PART_SLICE) {
1211 snprintf(name, sizeof name, "%s-%d", c1->name, entries);
1212 if ((cp = variable_get(name)) != NULL) {
1214 char typ[10], mpoint[50];
1216 if (sscanf(cp, "%s %d %s", typ, &sz, mpoint) != 3) {
1217 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp);
1218 status = DITEM_FAILURE;
1224 if (!strcmp(typ, "swap")) {
1226 strcpy(mpoint, "SWAP");
1229 type = PART_FILESYSTEM;
1230 if (!strcmp(mpoint, "/"))
1231 flags |= CHUNK_IS_ROOT;
1233 flags &= ~CHUNK_IS_ROOT;
1236 sz = space_free(c1);
1237 if (sz > space_free(c1)) {
1238 msgConfirm("Not enough free space to create partition: %s", mpoint);
1239 status = DITEM_FAILURE;
1242 if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part,
1243 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) {
1244 msgConfirm("Unable to create from partition spec: %s. Too big?", cp);
1245 status = DITEM_FAILURE;
1249 tmp->private_data = new_part(mpoint, TRUE, sz);
1250 tmp->private_free = safe_free;
1251 status = DITEM_SUCCESS;
1257 /* No more matches, leave the loop */
1263 /* Must be something we can set a mountpoint for */
1264 cp = variable_get(c1->name);
1266 char mpoint[50], do_newfs[8];
1267 Boolean newfs = FALSE;
1270 if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) {
1271 msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp);
1272 status = DITEM_FAILURE;
1275 newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE;
1276 if (c1->private_data) {
1277 p = c1->private_data;
1279 strcpy(p->mountpoint, mpoint);
1282 c1->private_data = new_part(mpoint, newfs, 0);
1283 c1->private_free = safe_free;
1285 if (!strcmp(mpoint, "/"))
1286 c1->flags |= CHUNK_IS_ROOT;
1288 c1->flags &= ~CHUNK_IS_ROOT;
1292 if (status == DITEM_SUCCESS)
1293 variable_set2(DISK_LABELLED, "yes", 0);