bsdinstall/partedit: Replace libdialog with libbsddialog

bsdinstall/partedit: Replace (LGPL) libdialog with (BSD-2-Clause)
libbsddialog. Rewrite diskeditor.c and rename diskmenu.c because
it uses an API for menu totally incompatible with libbsddialog.
This is a User Interface change everything else is unchanged.

Approved by:		bapt (mentor)
Differential Revision:	https://reviews.freebsd.org/D34639
This commit is contained in:
Alfonso S. Siciliano 2022-04-04 01:52:00 +02:00
parent e86707418c
commit 50e244964e
No known key found for this signature in database
GPG Key ID: 3F9EEFACFD371E37
7 changed files with 524 additions and 606 deletions

View File

@ -5,7 +5,8 @@ PROG= partedit
LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \
${BINDIR}/partedit ${BINDIR}/scriptedpart
SYMLINKS= ../libexec/bsdinstall/partedit /usr/sbin/sade
LIBADD+= geom ncursesw util dialog m
CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib
LIBADD+= geom util bsddialog
PARTEDIT_ARCH= ${MACHINE}
.if ${MACHINE} == "i386" || ${MACHINE} == "amd64"
@ -17,7 +18,7 @@ PARTEDIT_ARCH= efi
PARTEDIT_ARCH= generic
.endif
SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
SRCS= diskmenu.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
part_wizard.c scripted.c
WARNS?= 3

View File

@ -1,292 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2011 Nathan Whitehorn
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stdio.h>
#include <unistd.h>
#include <libutil.h>
#include <dialog.h>
#include <dlg_keys.h>
#include "diskeditor.h"
static void
print_partedit_item(WINDOW *partitions, struct partedit_item *items,
int item, int nscroll, int selected)
{
chtype attr = A_NORMAL;
char sizetext[16];
int y = item - nscroll + 1;
wattrset(partitions, selected ? item_selected_attr : item_attr);
wmove(partitions, y, MARGIN + items[item].indentation*2);
dlg_print_text(partitions, items[item].name, 10, &attr);
wmove(partitions, y, 17);
wattrset(partitions, item_attr);
humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
HN_DECIMAL);
dlg_print_text(partitions, sizetext, 8, &attr);
wmove(partitions, y, 25);
dlg_print_text(partitions, items[item].type, 15, &attr);
wmove(partitions, y, 40);
if (items[item].mountpoint != NULL)
dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
}
int
diskeditor_show(const char *title, const char *cprompt,
struct partedit_item *items, int nitems, int *selected, int *nscroll)
{
WINDOW *dialog, *partitions;
char *prompt;
const char *buttons[] =
{ "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
const char *help_text[] = {
"Add a new partition", "Delete selected partition or partitions",
"Change partition type or mountpoint",
"Revert changes to disk setup", "Use guided partitioning tool",
"Exit partitioner (will ask whether to save changes)", NULL };
int x, y;
int i;
int height, width, min_width;
int partlist_height, partlist_width;
int cur_scroll = 0;
int key, fkey;
int cur_button = 5, cur_part = 0;
int result = DLG_EXIT_UNKNOWN;
static DLG_KEYS_BINDING binding[] = {
ENTERKEY_BINDINGS,
DLG_KEYS_DATA( DLGK_ENTER, ' ' ),
DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
SCROLLKEY_BINDINGS,
END_KEYS_BINDING
};
static DLG_KEYS_BINDING binding2[] = {
INPUTSTR_BINDINGS,
ENTERKEY_BINDINGS,
DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ),
DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ),
DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ),
DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ),
DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ),
DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ),
END_KEYS_BINDING
};
/*
* Set up editor window.
*/
prompt = dlg_strclone(cprompt);
min_width = 50;
height = width = 0;
partlist_height = 10;
dlg_tab_correct_str(prompt);
dlg_button_layout(buttons, &min_width);
dlg_auto_size(title, prompt, &height, &width, 2, min_width);
height += partlist_height;
partlist_width = width - 2*MARGIN;
dlg_print_size(height, width);
dlg_ctl_size(height, width);
x = dlg_box_x_ordinate(width);
y = dlg_box_y_ordinate(height);
dialog = dlg_new_window(height, width, y, x);
dlg_register_window(dialog, "diskeditorbox", binding);
dlg_register_buttons(dialog, "diskeditorbox", buttons);
dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
dlg_draw_bottom_box(dialog);
dlg_draw_title(dialog, title);
wattrset(dialog, dialog_attr);
/* Partition list sub-window */
partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
y + 3, x + 1);
dlg_register_window(partitions, "partlist", binding2);
dlg_register_buttons(partitions, "partlist", buttons);
wattrset(partitions, menubox_attr);
dlg_item_help(help_text[cur_button]);
dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
cur_button, FALSE, width);
dlg_print_autowrap(dialog, prompt, height, width);
if (selected != NULL)
cur_part = *selected;
if (nscroll != NULL)
cur_scroll = *nscroll;
if (cur_part - cur_scroll >= partlist_height - 2 ||
cur_part - cur_scroll < 0)
cur_scroll = cur_part;
repaint:
dlg_draw_box(dialog, 3, 1, partlist_height, partlist_width,
menubox_border_attr, menubox_attr);
for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
i++)
print_partedit_item(partitions, items, i, cur_scroll,
i == cur_part);
if (nitems > partlist_height - 2)
dlg_draw_arrows(partitions, cur_scroll > 0,
nitems > cur_scroll + partlist_height - 2,
partlist_width - 5, 0, partlist_height - 1);
wrefresh(partitions);
while (result == DLG_EXIT_UNKNOWN) {
key = dlg_mouse_wgetch(dialog, &fkey);
if ((i = dlg_char_to_button(key, buttons)) >= 0) {
cur_button = i;
dlg_item_help(help_text[cur_button]);
dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
cur_button, FALSE, width);
break;
}
if (!fkey)
continue;
switch (key) {
case DLGK_FIELD_NEXT:
cur_button = dlg_next_button(buttons, cur_button);
if (cur_button < 0)
cur_button = 0;
dlg_item_help(help_text[cur_button]);
dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
cur_button, FALSE, width);
break;
case DLGK_FIELD_PREV:
cur_button = dlg_prev_button(buttons, cur_button);
if (cur_button < 0)
cur_button = 0;
dlg_item_help(help_text[cur_button]);
dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
cur_button, FALSE, width);
break;
case DLGK_ITEM_NEXT:
if (cur_part == nitems - 1)
break; /* End of list */
/* Deselect old item */
print_partedit_item(partitions, items, cur_part,
cur_scroll, 0);
/* Select new item */
cur_part++;
if (cur_part - cur_scroll >= partlist_height - 2) {
cur_scroll = cur_part;
goto repaint;
}
print_partedit_item(partitions, items, cur_part,
cur_scroll, 1);
wrefresh(partitions);
break;
case DLGK_ITEM_PREV:
if (cur_part == 0)
break; /* Start of list */
/* Deselect old item */
print_partedit_item(partitions, items, cur_part,
cur_scroll, 0);
/* Select new item */
cur_part--;
if (cur_part - cur_scroll < 0) {
cur_scroll = cur_part;
goto repaint;
}
print_partedit_item(partitions, items, cur_part,
cur_scroll, 1);
wrefresh(partitions);
break;
case DLGK_PAGE_NEXT:
cur_scroll += (partlist_height - 2);
if (cur_scroll + partlist_height - 2 >= nitems)
cur_scroll = nitems - (partlist_height - 2);
if (cur_scroll < 0)
cur_scroll = 0;
if (cur_part < cur_scroll)
cur_part = cur_scroll;
goto repaint;
case DLGK_PAGE_PREV:
cur_scroll -= (partlist_height - 2);
if (cur_scroll < 0)
cur_scroll = 0;
if (cur_part >= cur_scroll + partlist_height - 2)
cur_part = cur_scroll;
goto repaint;
case DLGK_PAGE_FIRST:
cur_scroll = 0;
cur_part = cur_scroll;
goto repaint;
case DLGK_PAGE_LAST:
cur_scroll = nitems - (partlist_height - 2);
if (cur_scroll < 0)
cur_scroll = 0;
cur_part = cur_scroll;
goto repaint;
case DLGK_ENTER:
goto done;
default:
if (is_DLGK_MOUSE(key)) {
cur_button = key - M_EVENT;
dlg_item_help(help_text[cur_button]);
dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
buttons, cur_button, FALSE, width);
goto done;
}
break;
}
}
done:
if (selected != NULL)
*selected = cur_part;
if (nscroll != NULL)
*nscroll = cur_scroll;
dlg_del_window(partitions);
dlg_del_window(dialog);
dlg_mouse_free_regions();
return (cur_button);
}

View File

@ -0,0 +1,90 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Alfonso Sabato Siciliano
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <bsddialog.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "diskmenu.h"
int
diskmenu_show(const char *title, const char *text, struct partedit_item *items,
int nitems, int *focusitem)
{
int i, output;
char size[16], *mp;
struct bsddialog_menuitem *bsditems;
struct bsddialog_conf conf;
bsditems = malloc(nitems * sizeof(struct bsddialog_menuitem));
if (bsditems == NULL)
return BSDDIALOG_ERROR;
for (i = 0; i < nitems; i++) {
bsditems[i].prefix = "";
bsditems[i].on = false;
bsditems[i].depth = items[i].indentation;
/* old menu sets max namelen to 10 */
bsditems[i].name = items[i].name;
humanize_number(size, 7, items[i].size, "B",
HN_AUTOSCALE, HN_DECIMAL);
mp = items[i].mountpoint != NULL ? items[i].mountpoint : "";
asprintf(__DECONST(char**, &bsditems[i].desc), "%s %-15s %-10s",
size, items[i].type, mp);
bsditems[i].bottomdesc = "";
}
bsddialog_initconf(&conf);
conf.title = title;
conf.menu.align_left = true;
conf.text.highlight = true;
conf.key.f1_message="[\\Z1\\ZbC\\Znreate]: a new partition.\n"
"[\\Z1\\ZbD\\Znelete]: selected partition(s).\n"
"[\\Z1\\ZbC\\Znhange]: partition type or mountpoint.\n"
"[\\Z1\\ZbR\\Znevert]: changes to disk setup.\n"
"[\\Z1\\ZbA\\Znuto]: guided partitioning tool.\n"
"[\\Z1\\ZbF\\Zninish]: will ask to apply changes.";
conf.menu.shortcut_buttons = true;
conf.button.ok_label = "Create";
conf.button.with_extra = true;
conf.button.extra_label = "Delete";
conf.button.cancel_label = "Modify";
conf.button.with_help = true;
conf.button.help_label = "Revert";
conf.button.generic1_label = "Auto";
conf.button.generic2_label = "Finish";
conf.button.default_label = "Finish";
output = bsddialog_menu(&conf, text, 20, 0, 10, nitems, bsditems,
focusitem);
for (i = 0; i < nitems; i++)
free((char *)bsditems[i].desc);
free(bsditems);
return output;
}

View File

@ -28,10 +28,15 @@
* $FreeBSD$
*/
#ifndef _PARTEDIT_DISKEDITOR_H
#define _PARTEDIT_DISKEDITOR_H
#ifndef _PARTEDIT_DISKMENU_H
#define _PARTEDIT_DISKMENU_H
#include <inttypes.h>
#define BUTTON_CREATE BSDDIALOG_OK
#define BUTTON_DELETE BSDDIALOG_EXTRA
#define BUTTON_MODIFY BSDDIALOG_CANCEL
#define BUTTON_REVERT BSDDIALOG_HELP
#define BUTTON_AUTO BSDDIALOG_GENERIC1
#define BUTTON_FINISH BSDDIALOG_GENERIC2
struct partedit_item {
int indentation;
@ -43,7 +48,7 @@ struct partedit_item {
void *cookie;
};
int diskeditor_show(const char *title, const char *prompt,
struct partedit_item *items, int nitems, int *selected, int *scroll);
int diskmenu_show(const char *title, const char *text,
struct partedit_item *items, int nitems, int *selected);
#endif

View File

@ -30,14 +30,19 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <bsddialog.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgeom.h>
#include <dialog.h>
#include <dlg_keys.h>
#include "partedit.h"
@ -49,6 +54,7 @@ gpart_show_error(const char *title, const char *explanation, const char *errstr)
char *errmsg;
char message[512];
int error;
struct bsddialog_conf conf;
if (explanation == NULL)
explanation = "";
@ -66,7 +72,9 @@ gpart_show_error(const char *title, const char *explanation, const char *errstr)
sprintf(message, "%s%s", explanation, errmsg);
}
dialog_msgbox(title, message, 0, 0, TRUE);
bsddialog_initconf(&conf);
conf.title = title;
bsddialog_msgbox(&conf, message, 0, 0);
}
static int
@ -83,34 +91,38 @@ scheme_supports_labels(const char *scheme)
static void
newfs_command(const char *fstype, char *command, int use_default)
{
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
if (strcmp(fstype, "freebsd-ufs") == 0) {
int i;
DIALOG_LISTITEM items[] = {
{"UFS1", "UFS Version 1",
struct bsddialog_menuitem items[] = {
{"", false, 0, "UFS1", "UFS Version 1",
"Use version 1 of the UFS file system instead "
"of version 2 (not recommended)", 0 },
{"SU", "Softupdates",
"Enable softupdates (default)", 1 },
{"SUJ", "Softupdates journaling",
"of version 2 (not recommended)"},
{"", true, 0, "SU", "Softupdates",
"Enable softupdates (default)"},
{"", true, 0, "SUJ", "Softupdates journaling",
"Enable file system journaling (default - "
"turn off for SSDs)", 1 },
{"TRIM", "Enable SSD TRIM support",
"Enable TRIM support, useful on solid-state drives",
0 },
"turn off for SSDs)"},
{"", false, 0, "TRIM", "Enable SSD TRIM support",
"Enable TRIM support, useful on solid-state "
"drives" },
};
if (!use_default) {
int choice;
choice = dlg_checklist("UFS Options", "", 0, 0, 0,
nitems(items), items, NULL,
FLAG_CHECK, &i);
if (choice == 1) /* Cancel */
conf.title = "UFS Options";
choice = bsddialog_checklist(&conf, "", 0, 0, 0,
nitems(items), items, NULL);
if (choice == BSDDIALOG_CANCEL)
return;
}
strcpy(command, "newfs ");
for (i = 0; i < (int)nitems(items); i++) {
if (items[i].state == 0)
if (items[i].on == false)
continue;
if (strcmp(items[i].name, "UFS1") == 0)
strcat(command, "-O1 ");
@ -123,26 +135,26 @@ newfs_command(const char *fstype, char *command, int use_default)
}
} else if (strcmp(fstype, "freebsd-zfs") == 0) {
int i;
DIALOG_LISTITEM items[] = {
{"fletcher4", "checksum algorithm: fletcher4",
struct bsddialog_menuitem items[] = {
{"", 0, true, "fletcher4", "checksum algorithm: fletcher4",
"Use fletcher4 for data integrity checking. "
"(default)", 1 },
{"fletcher2", "checksum algorithm: fletcher2",
"(default)"},
{"", 0, false, "fletcher2", "checksum algorithm: fletcher2",
"Use fletcher2 for data integrity checking. "
"(not recommended)", 0 },
{"sha256", "checksum algorithm: sha256",
"(not recommended)"},
{"", 0, false, "sha256", "checksum algorithm: sha256",
"Use sha256 for data integrity checking. "
"(not recommended)", 0 },
{"atime", "Update atimes for files",
"Disable atime update", 0 },
"(not recommended)"},
{"", 0, false, "atime", "Update atimes for files",
"Disable atime update"},
};
if (!use_default) {
int choice;
choice = dlg_checklist("ZFS Options", "", 0, 0, 0,
nitems(items), items, NULL,
FLAG_CHECK, &i);
if (choice == 1) /* Cancel */
conf.title = "ZFS Options";
choice = bsddialog_checklist(&conf, "", 0, 0, 0,
nitems(items), items, NULL);
if (choice == BSDDIALOG_CANCEL)
return;
}
@ -157,7 +169,7 @@ newfs_command(const char *fstype, char *command, int use_default)
command, zfsboot_path);
}
for (i = 0; i < (int)nitems(items); i++) {
if (items[i].state == 0)
if (items[i].on == false)
continue;
if (strcmp(items[i].name, "fletcher4") == 0)
strcat(command, "-O checksum=fletcher4 ");
@ -171,27 +183,27 @@ newfs_command(const char *fstype, char *command, int use_default)
} else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 ||
strcmp(fstype, "ms-basic-data") == 0) {
int i;
DIALOG_LISTITEM items[] = {
{"FAT32", "FAT Type 32",
"Create a FAT32 filesystem (default)", 1 },
{"FAT16", "FAT Type 16",
"Create a FAT16 filesystem", 0 },
{"FAT12", "FAT Type 12",
"Create a FAT12 filesystem", 0 },
struct bsddialog_menuitem items[] = {
{"", 0, true, "FAT32", "FAT Type 32",
"Create a FAT32 filesystem (default)"},
{"", 0, false, "FAT16", "FAT Type 16",
"Create a FAT16 filesystem"},
{"", 0, false, "FAT12", "FAT Type 12",
"Create a FAT12 filesystem"},
};
if (!use_default) {
int choice;
choice = dlg_checklist("FAT Options", "", 0, 0, 0,
nitems(items), items, NULL,
FLAG_RADIO, &i);
if (choice == 1) /* Cancel */
conf.title = "FAT Options";
choice = bsddialog_radiolist(&conf, "", 0, 0, 0,
nitems(items), items, NULL);
if (choice == BSDDIALOG_CANCEL)
return;
}
strcpy(command, "newfs_msdos ");
for (i = 0; i < (int)nitems(items); i++) {
if (items[i].state == 0)
if (items[i].on == false)
continue;
if (strcmp(items[i].name, "FAT32") == 0)
strcat(command, "-F 32 -c 1");
@ -201,9 +213,11 @@ newfs_command(const char *fstype, char *command, int use_default)
strcat(command, "-F 12 ");
}
} else {
if (!use_default)
dialog_msgbox("Error", "No configurable options exist "
"for this filesystem.", 0, 0, TRUE);
if (!use_default) {
conf.title = "Error";
bsddialog_msgbox(&conf, "No configurable options exist "
"for this filesystem.", 0, 0);
}
command[0] = '\0';
}
}
@ -211,28 +225,34 @@ newfs_command(const char *fstype, char *command, int use_default)
const char *
choose_part_type(const char *def_scheme)
{
int cancel, choice;
int button, choice, i;
const char *scheme = NULL;
struct bsddialog_conf conf;
DIALOG_LISTITEM items[] = {
{"APM", "Apple Partition Map",
"Bootable on PowerPC Apple Hardware", 0 },
{"BSD", "BSD Labels",
"Bootable on most x86 systems", 0 },
{"GPT", "GUID Partition Table",
"Bootable on most x86 systems and EFI aware ARM64", 0 },
{"MBR", "DOS Partitions",
"Bootable on most x86 systems", 0 },
struct bsddialog_menuitem items[] = {
{"", false, 0, "APM", "Apple Partition Map",
"Bootable on PowerPC Apple Hardware" },
{"", false, 0, "BSD", "BSD Labels",
"Bootable on most x86 systems" },
{"", false, 0, "GPT", "GUID Partition Table",
"Bootable on most x86 systems and EFI aware ARM64" },
{"", false, 0, "MBR", "DOS Partitions",
"Bootable on most x86 systems" },
};
parttypemenu:
dialog_vars.default_item = __DECONST(char *, def_scheme);
cancel = dlg_menu("Partition Scheme",
"Select a partition scheme for this volume:", 0, 0, 0,
nitems(items), items, &choice, NULL);
dialog_vars.default_item = NULL;
for (i = 0; i < (int)nitems(items); i++)
if (strcmp(items[i].name, def_scheme) == 0)
choice = i;
if (cancel)
bsddialog_initconf(&conf);
parttypemenu:
conf.title = "Partition Scheme";
button = bsddialog_menu(&conf,
"Select a partition scheme for this volume:", 0, 0, 0,
nitems(items), items, &choice);
if (button == BSDDIALOG_CANCEL)
return NULL;
if (!is_scheme_bootable(items[choice].name)) {
@ -240,10 +260,11 @@ choose_part_type(const char *def_scheme)
sprintf(message, "This partition scheme (%s) is not "
"bootable on this platform. Are you sure you want "
"to proceed?", items[choice].name);
dialog_vars.defaultno = TRUE;
cancel = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (cancel) /* cancel */
conf.button.default_cancel = true;
conf.title = "Warning";
button = bsddialog_yesno(&conf, message, 0, 0);
conf.button.default_cancel = false;
if (button == BSDDIALOG_NO)
goto parttypemenu;
}
@ -255,9 +276,12 @@ choose_part_type(const char *def_scheme)
int
gpart_partition(const char *lg_name, const char *scheme)
{
int cancel;
int button;
struct gctl_req *r;
const char *errstr;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
schememenu:
if (scheme == NULL) {
@ -271,10 +295,11 @@ gpart_partition(const char *lg_name, const char *scheme)
sprintf(message, "This partition scheme (%s) is not "
"bootable on this platform. Are you sure you want "
"to proceed?", scheme);
dialog_vars.defaultno = TRUE;
cancel = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (cancel) { /* cancel */
conf.button.default_cancel = true;
conf.title = "Warning";
button = bsddialog_yesno(&conf, message, 0, 0);
conf.button.default_cancel = false;
if (button == BSDDIALOG_NO) {
/* Reset scheme so user can choose another */
scheme = NULL;
goto schememenu;
@ -379,6 +404,7 @@ gpart_bootcode(struct ggeom *gp)
uint8_t *boot;
size_t bootsize, bytes;
int bootfd;
struct bsddialog_conf conf;
/*
* Write default bootcode to the newly partitioned disk, if that
@ -397,8 +423,9 @@ gpart_bootcode(struct ggeom *gp)
bootfd = open(bootcode, O_RDONLY);
if (bootfd < 0) {
dialog_msgbox("Bootcode Error", strerror(errno), 0, 0,
TRUE);
bsddialog_initconf(&conf);
conf.title = "Bootcode Error";
bsddialog_msgbox(&conf, strerror(errno), 0, 0);
return;
}
@ -430,6 +457,7 @@ gpart_partcode(struct gprovider *pp, const char *fstype)
const char *scheme;
const char *indexstr;
char message[255], command[255];
struct bsddialog_conf conf;
LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) {
if (strcmp(gc->lg_name, "scheme") == 0) {
@ -455,7 +483,9 @@ gpart_partcode(struct gprovider *pp, const char *fstype)
if (system(command) != 0) {
sprintf(message, "Error installing partcode on partition %s",
pp->lg_name);
dialog_msgbox("Error", message, 0, 0, TRUE);
bsddialog_initconf(&conf);
conf.title = "Error";
bsddialog_msgbox(&conf, message, 0, 0);
}
}
@ -513,24 +543,26 @@ gpart_edit(struct gprovider *pp)
char sizestr[32];
char newfs[255];
intmax_t idx;
int hadlabel, choice, junk, nitems;
int hadlabel, choice, nitems;
unsigned i;
struct bsddialog_conf conf;
DIALOG_FORMITEM items[] = {
{0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0,
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)", FALSE},
{0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 0, 0,
FALSE, "Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes.", FALSE},
{0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0,
FALSE, "Path at which to mount this partition (leave blank "
"for swap, set to / for root filesystem)", FALSE},
{0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE,
"Partition name. Not all partition schemes support this.",
FALSE},
struct bsddialog_formitem items[] = {
{ "Type:", 1, 1, "", 1, 12, 12, 15, NULL, 0,
"Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)"},
{ "Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0,
"Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes."},
{ "Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0,
"Path at which to mount this partition (leave blank "
"for swap, set to / for root filesystem)"},
{ "Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0,
"Partition name. Not all partition schemes support this."},
};
bsddialog_initconf(&conf);
/*
* Find the PART geom we are manipulating. This may be a consumer of
* this provider, or its parent. Check the consumer case first.
@ -586,11 +618,11 @@ gpart_edit(struct gprovider *pp)
LIST_FOREACH(gc, &pp->lg_config, lg_config) {
if (strcmp(gc->lg_name, "type") == 0) {
oldtype = gc->lg_val;
items[0].text = gc->lg_val;
items[0].init = gc->lg_val;
}
if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) {
hadlabel = 1;
items[3].text = gc->lg_val;
items[3].init = gc->lg_val;
}
if (strcmp(gc->lg_name, "index") == 0)
idx = atoi(gc->lg_val);
@ -599,39 +631,43 @@ gpart_edit(struct gprovider *pp)
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) {
if (md->fstab != NULL)
items[2].text = md->fstab->fs_file;
items[2].init = md->fstab->fs_file;
break;
}
}
humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE,
HN_NOSPACE | HN_DECIMAL);
items[1].text = sizestr;
items[1].init = sizestr;
editpart:
choice = dlg_form("Edit Partition", "", 0, 0, 0, nitems, items, &junk);
conf.form.value_without_ok = true;
conf.title = "Edit Partition";
choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items);
if (choice) /* Cancel pressed */
if (choice == BSDDIALOG_CANCEL)
goto endedit;
/* If this is the root partition, check that this fs is bootable */
if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
items[0].text)) {
if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme,
items[0].value)) {
char message[512];
sprintf(message, "This file system (%s) is not bootable "
"on this system. Are you sure you want to proceed?",
items[0].text);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
items[0].value);
conf.button.default_cancel = true;
conf.title = "Warning";
choice = bsddialog_yesno(&conf, message, 0, 0);
conf.button.default_cancel = false;
if (choice == BSDDIALOG_CANCEL)
goto editpart;
}
/* Check if the label has a / in it */
if (strchr(items[3].text, '/') != NULL) {
dialog_msgbox("Error", "Label contains a /, which is not an "
"allowed character.", 0, 0, TRUE);
if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) {
conf.title = "Error";
bsddialog_msgbox(&conf, "Label contains a /, which is not an "
"allowed character.", 0, 0);
goto editpart;
}
@ -641,9 +677,9 @@ gpart_edit(struct gprovider *pp)
gctl_ro_param(r, "flags", -1, GPART_FLAGS);
gctl_ro_param(r, "verb", -1, "modify");
gctl_ro_param(r, "index", sizeof(idx), &idx);
if (hadlabel || items[3].text[0] != '\0')
gctl_ro_param(r, "label", -1, items[3].text);
gctl_ro_param(r, "type", -1, items[0].text);
if (items[3].value != NULL && (hadlabel || items[3].value[0] != '\0'))
gctl_ro_param(r, "label", -1, items[3].value);
gctl_ro_param(r, "type", -1, items[0].value);
errstr = gctl_issue(r);
if (errstr != NULL && errstr[0] != '\0') {
gpart_show_error("Error", NULL, errstr);
@ -652,21 +688,21 @@ gpart_edit(struct gprovider *pp)
}
gctl_free(r);
newfs_command(items[0].text, newfs, 1);
set_default_part_metadata(pp->lg_name, scheme, items[0].text,
items[2].text, (strcmp(oldtype, items[0].text) != 0) ?
newfs_command(items[0].value, newfs, 1);
set_default_part_metadata(pp->lg_name, scheme, items[0].value,
items[2].value, (strcmp(oldtype, items[0].value) != 0) ?
newfs : NULL);
endedit:
if (strcmp(oldtype, items[0].text) != 0 && cp != NULL)
if (strcmp(oldtype, items[0].value) != 0 && cp != NULL)
gpart_destroy(cp->lg_geom);
if (strcmp(oldtype, items[0].text) != 0 && strcmp(items[0].text,
if (strcmp(oldtype, items[0].value) != 0 && strcmp(items[0].value,
"freebsd") == 0)
gpart_partition(pp->lg_name, "BSD");
for (i = 0; i < nitems(items); i++)
if (items[i].text_free)
free(items[i].text);
if (items[i].value != NULL)
free(items[i].value);
}
void
@ -894,6 +930,7 @@ add_boot_partition(struct ggeom *geom, struct gprovider *pp,
struct gconfig *gc;
struct gprovider *ppi;
int choice;
struct bsddialog_conf conf;
/* Check for existing freebsd-boot partition */
LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) {
@ -931,15 +968,18 @@ add_boot_partition(struct ggeom *geom, struct gprovider *pp,
return (0);
}
if (interactive)
choice = dialog_yesno("Boot Partition",
if (interactive) {
bsddialog_initconf(&conf);
conf.title = "Boot Partition";
choice = bsddialog_yesno(&conf,
"This partition scheme requires a boot partition "
"for the disk to be bootable. Would you like to "
"make one now?", 0, 0);
else
choice = 0;
} else {
choice = BSDDIALOG_YES;
}
if (choice == 0) { /* yes */
if (choice == BSDDIALOG_YES) {
struct partition_metadata *md;
const char *bootmount = NULL;
char *bootpartname = NULL;
@ -988,22 +1028,25 @@ gpart_create(struct gprovider *pp, const char *default_type,
uint64_t bytes;
int nitems, choice, junk;
unsigned i;
bool init_allocated;
struct bsddialog_conf conf;
DIALOG_FORMITEM items[] = {
{0, "Type:", 5, 0, 0, FALSE, "freebsd-ufs", 11, 0, 12, 15, 0,
FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)", FALSE},
{0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 15, 0,
FALSE, "Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes.", FALSE},
{0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0,
FALSE, "Path at which to mount partition (blank for "
"swap, / for root filesystem)", FALSE},
{0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE,
"Partition name. Not all partition schemes support this.",
FALSE},
struct bsddialog_formitem items[] = {
{"Type:", 1, 1, "freebsd-ufs", 1, 12, 12, 15, NULL, 0,
"Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
"freebsd-swap)"},
{"Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0,
"Partition size. Append K, M, G for kilobytes, "
"megabytes or gigabytes."},
{"Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0,
"Path at which to mount partition (blank for "
"swap, / for root filesystem)"},
{"Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0,
"Partition name. Not all partition schemes support this."},
};
bsddialog_initconf(&conf);
if (partname != NULL)
*partname = NULL;
@ -1034,11 +1077,12 @@ gpart_create(struct gprovider *pp, const char *default_type,
}
if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) {
if (gpart_partition(pp->lg_name, NULL) == 0)
dialog_msgbox("",
if (gpart_partition(pp->lg_name, NULL) == 0) {
bsddialog_msgbox(&conf,
"The partition table has been successfully created."
" Please press Create again to create partitions.",
0, 0, TRUE);
0, 0);
}
return;
}
@ -1053,50 +1097,61 @@ gpart_create(struct gprovider *pp, const char *default_type,
maxsize = size = gpart_max_free(geom, &firstfree);
if (size <= 0) {
dialog_msgbox("Error", "No free space left on device.", 0, 0,
TRUE);
conf .title = "Error";
bsddialog_msgbox(&conf, "No free space left on device.", 0, 0);
return;
}
humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE,
HN_NOSPACE | HN_DECIMAL);
items[1].text = sizestr;
items[1].init = sizestr;
/* Special-case the MBR default type for nested partitions */
if (strcmp(scheme, "MBR") == 0) {
items[0].text = "freebsd";
items[0].help = "Filesystem type (e.g. freebsd, fat32)";
items[0].init = "freebsd";
items[0].bottomdesc = "Filesystem type (e.g. freebsd, fat32)";
}
nitems = scheme_supports_labels(scheme) ? 4 : 3;
if (default_type != NULL)
items[0].text = (char *)default_type;
items[0].init = (char *)default_type;
if (default_size != NULL)
items[1].text = (char *)default_size;
items[1].init = (char *)default_size;
if (default_mountpoint != NULL)
items[2].text = (char *)default_mountpoint;
items[2].init = (char *)default_mountpoint;
/* Default options */
strncpy(options_fstype, items[0].text,
strncpy(options_fstype, items[0].init,
sizeof(options_fstype));
newfs_command(options_fstype, newfs, 1);
init_allocated = false;
addpartform:
if (interactive) {
dialog_vars.extra_label = "Options";
dialog_vars.extra_button = TRUE;
choice = dlg_form("Add Partition", "", 0, 0, 0, nitems,
items, &junk);
dialog_vars.extra_button = FALSE;
conf.button.with_extra = true;
conf.button.extra_label = "Options";
conf.form.value_without_ok = true;
conf.title = "Add Partition";
choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items);
conf.button.with_extra = false;
conf.button.extra_label = NULL;
conf.form.value_without_ok = false;
switch (choice) {
case 0: /* OK */
case BSDDIALOG_OK:
break;
case 1: /* Cancel */
case BSDDIALOG_CANCEL:
return;
case 3: /* Options */
strncpy(options_fstype, items[0].text,
case BSDDIALOG_EXTRA: /* Options */
strncpy(options_fstype, items[0].value,
sizeof(options_fstype));
newfs_command(options_fstype, newfs, 0);
for (i = 0; i < nitems(items); i++) {
if (init_allocated)
free((char*)items[i].init);
items[i].init = items[i].value;
}
init_allocated = true;
goto addpartform;
}
}
@ -1105,45 +1160,48 @@ gpart_create(struct gprovider *pp, const char *default_type,
* If the user changed the fs type after specifying options, undo
* their choices in favor of the new filesystem's defaults.
*/
if (strcmp(options_fstype, items[0].text) != 0) {
strncpy(options_fstype, items[0].text, sizeof(options_fstype));
if (strcmp(options_fstype, items[0].value) != 0) {
strncpy(options_fstype, items[0].value, sizeof(options_fstype));
newfs_command(options_fstype, newfs, 1);
}
size = maxsize;
if (strlen(items[1].text) > 0) {
if (expand_number(items[1].text, &bytes) != 0) {
if (strlen(items[1].value) > 0) {
if (expand_number(items[1].value, &bytes) != 0) {
char error[512];
sprintf(error, "Invalid size: %s\n", strerror(errno));
dialog_msgbox("Error", error, 0, 0, TRUE);
conf.title = "Error";
bsddialog_msgbox(&conf, error, 0, 0);
goto addpartform;
}
size = MIN((intmax_t)(bytes/sector), maxsize);
}
/* Check if the label has a / in it */
if (strchr(items[3].text, '/') != NULL) {
dialog_msgbox("Error", "Label contains a /, which is not an "
"allowed character.", 0, 0, TRUE);
if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) {
conf.title = "Error";
bsddialog_msgbox(&conf, "Label contains a /, which is not an "
"allowed character.", 0, 0);
goto addpartform;
}
/* Warn if no mountpoint set */
if (strcmp(items[0].text, "freebsd-ufs") == 0 &&
items[2].text[0] != '/') {
if (strcmp(items[0].value, "freebsd-ufs") == 0 &&
items[2].value[0] != '/') {
choice = 0;
if (interactive) {
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning",
conf.button.default_cancel = true;
conf.title = "Warning";
choice = bsddialog_yesno(&conf,
"This partition does not have a valid mountpoint "
"(for the partition from which you intend to boot the "
"operating system, the mountpoint should be /). Are you "
"sure you want to continue?"
, 0, 0);
dialog_vars.defaultno = FALSE;
conf.button.default_cancel = false;
}
if (choice == 1) /* cancel */
if (choice == BSDDIALOG_CANCEL)
goto addpartform;
}
@ -1151,39 +1209,42 @@ gpart_create(struct gprovider *pp, const char *default_type,
* Error if this scheme needs nested partitions, this is one, and
* a mountpoint was set.
*/
if (strcmp(items[0].text, "freebsd") == 0 &&
strlen(items[2].text) > 0) {
dialog_msgbox("Error", "Partitions of type \"freebsd\" are "
if (strcmp(items[0].value, "freebsd") == 0 &&
strlen(items[2].value) > 0) {
conf.title = "Error";
bsddialog_msgbox(&conf, "Partitions of type \"freebsd\" are "
"nested BSD-type partition schemes and cannot have "
"mountpoints. After creating one, select it and press "
"Create again to add the actual file systems.", 0, 0, TRUE);
"Create again to add the actual file systems.", 0, 0);
goto addpartform;
}
/* If this is the root partition, check that this scheme is bootable */
if (strcmp(items[2].text, "/") == 0 && !is_scheme_bootable(scheme)) {
if (strcmp(items[2].value, "/") == 0 && !is_scheme_bootable(scheme)) {
char message[512];
sprintf(message, "This partition scheme (%s) is not bootable "
"on this platform. Are you sure you want to proceed?",
scheme);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
conf.button.default_cancel = true;
conf.title = "Warning";
choice = bsddialog_yesno(&conf, message, 0, 0);
conf.button.default_cancel = false;
if (choice == BSDDIALOG_CANCEL)
goto addpartform;
}
/* If this is the root partition, check that this fs is bootable */
if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
items[0].text)) {
if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme,
items[0].value)) {
char message[512];
sprintf(message, "This file system (%s) is not bootable "
"on this system. Are you sure you want to proceed?",
items[0].text);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
items[0].value);
conf.button.default_cancel = true;
conf.title = "Warning";
choice = bsddialog_yesno(&conf, message, 0, 0);
conf.button.default_cancel = false;
if (choice == BSDDIALOG_CANCEL)
goto addpartform;
}
@ -1192,8 +1253,8 @@ gpart_create(struct gprovider *pp, const char *default_type,
* the user to add one.
*/
if ((strcmp(items[0].text, "freebsd") == 0 ||
strcmp(items[2].text, "/") == 0) && bootpart_size(scheme) > 0) {
if ((strcmp(items[0].value, "freebsd") == 0 ||
strcmp(items[2].value, "/") == 0) && bootpart_size(scheme) > 0) {
size_t bytes = add_boot_partition(geom, pp, scheme,
interactive);
@ -1214,13 +1275,14 @@ gpart_create(struct gprovider *pp, const char *default_type,
gctl_ro_param(r, "arg0", -1, geom->lg_name);
gctl_ro_param(r, "flags", -1, GPART_FLAGS);
gctl_ro_param(r, "verb", -1, "add");
gctl_ro_param(r, "type", -1, items[0].text);
gctl_ro_param(r, "type", -1, items[0].value);
snprintf(sizestr, sizeof(sizestr), "%jd", size);
gctl_ro_param(r, "size", -1, sizestr);
snprintf(startstr, sizeof(startstr), "%jd", firstfree);
gctl_ro_param(r, "start", -1, startstr);
if (items[3].text[0] != '\0')
gctl_ro_param(r, "label", -1, items[3].text);
if (items[3].value != NULL && items[3].value[0] != '\0')
gctl_ro_param(r, "label", -1, items[3].value);
gctl_add_param(r, "output", sizeof(output), output,
GCTL_PARAM_WR | GCTL_PARAM_ASCII);
errstr = gctl_issue(r);
@ -1247,15 +1309,19 @@ gpart_create(struct gprovider *pp, const char *default_type,
gctl_free(r);
if (strcmp(items[0].text, "freebsd") == 0)
if (strcmp(items[0].value, "freebsd") == 0)
gpart_partition(newpartname, "BSD");
else
set_default_part_metadata(newpartname, scheme,
items[0].text, items[2].text, newfs);
items[0].value, items[2].value, newfs);
for (i = 0; i < nitems(items); i++)
if (items[i].text_free)
free(items[i].text);
for (i = 0; i < nitems(items); i++) {
if (items[i].value != NULL) {
free(items[i].value);
if (init_allocated && items[i].init != NULL)
free((char*)items[i].init);
}
}
if (partname != NULL)
*partname = strdup(newpartname);
@ -1271,6 +1337,7 @@ gpart_delete(struct gprovider *pp)
const char *errstr;
intmax_t idx;
int is_partition;
struct bsddialog_conf conf;
/* Is it a partition? */
is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0);
@ -1304,9 +1371,12 @@ gpart_delete(struct gprovider *pp)
* error or no.
*/
if (!is_partition) {
if (geom == NULL)
dialog_msgbox("Error",
"Only partitions can be deleted.", 0, 0, TRUE);
if (geom == NULL) {
bsddialog_initconf(&conf);
conf.title = "Error";
bsddialog_msgbox(&conf,
"Only partitions can be deleted.", 0, 0);
}
return;
}
@ -1344,6 +1414,7 @@ gpart_revert_all(struct gmesh *mesh)
struct ggeom *gp;
struct gctl_req *r;
const char *modified;
struct bsddialog_conf conf;
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
if (strcmp(classp->lg_name, "PART") == 0)
@ -1351,7 +1422,9 @@ gpart_revert_all(struct gmesh *mesh)
}
if (strcmp(classp->lg_name, "PART") != 0) {
dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
bsddialog_initconf(&conf);
conf.title = "Error";
bsddialog_msgbox(&conf, "gpart not found!", 0, 0);
return;
}
@ -1391,6 +1464,7 @@ gpart_commit(struct gmesh *mesh)
const char *errstr;
const char *modified;
const char *rootfs;
struct bsddialog_conf conf;
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
if (strcmp(classp->lg_name, "PART") == 0)
@ -1407,7 +1481,9 @@ gpart_commit(struct gmesh *mesh)
}
if (strcmp(classp->lg_name, "PART") != 0) {
dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
bsddialog_initconf(&conf);
conf.title = "Error";
bsddialog_msgbox(&conf, "gpart not found!", 0, 0);
return;
}

View File

@ -29,14 +29,16 @@
*/
#include <sys/param.h>
#include <errno.h>
#include <inttypes.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgeom.h>
#include <dialog.h>
#include <dlg_keys.h>
#include <bsddialog.h>
#include "partedit.h"
@ -52,6 +54,9 @@ part_wizard(const char *fsreq)
const char *fstype;
struct gmesh mesh;
int error;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
if (fsreq != NULL)
fstype = fsreq;
@ -61,22 +66,22 @@ part_wizard(const char *fsreq)
startwizard:
error = geom_gettree(&mesh);
dlg_put_backtitle();
bsddialog_backtitle(&conf, "FreeBSD Installer");
error = geom_gettree(&mesh);
disk = boot_disk_select(&mesh);
if (disk == NULL)
return (1);
dlg_clear();
dlg_put_backtitle();
bsddialog_clearterminal();
bsddialog_backtitle(&conf, "FreeBSD Installer");
schemeroot = wizard_partition(&mesh, disk);
free(disk);
if (schemeroot == NULL)
return (1);
geom_deletetree(&mesh);
dlg_clear();
dlg_put_backtitle();
bsddialog_clearterminal();
bsddialog_backtitle(&conf, "FreeBSD Installer");
error = geom_gettree(&mesh);
error = wizard_makeparts(&mesh, schemeroot, fstype, 1);
@ -96,11 +101,14 @@ boot_disk_select(struct gmesh *mesh)
struct gconfig *gc;
struct ggeom *gp;
struct gprovider *pp;
DIALOG_LISTITEM *disks = NULL;
struct bsddialog_menuitem *disks = NULL;
const char *type, *desc;
char diskdesc[512];
char *chosen;
int i, err, selected, n = 0;
int i, button, selected, n = 0;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
if (strcmp(classp->lg_name, "DISK") != 0 &&
@ -143,19 +151,23 @@ boot_disk_select(struct gmesh *mesh)
snprintf(diskdesc, sizeof(diskdesc),
"%s <%s>", diskdesc, desc);
disks[n-1].text = strdup(diskdesc);
disks[n-1].help = NULL;
disks[n-1].state = 0;
disks[n-1].prefix = "";
disks[n-1].on = false;
disks[n-1].depth = 0;
disks[n-1].desc = strdup(diskdesc);
disks[n-1].bottomdesc = "";
}
}
}
if (n > 1) {
err = dlg_menu("Partitioning",
conf.title = "Partitioning";
button = bsddialog_menu(&conf,
"Select the disk on which to install FreeBSD.", 0, 0, 0,
n, disks, &selected, NULL);
n, disks, &selected);
chosen = (err == 0) ? strdup(disks[selected].name) : NULL;
chosen = (button == BSDDIALOG_OK) ?
strdup(disks[selected].name) : NULL;
} else if (n == 1) {
chosen = strdup(disks[0].name);
} else {
@ -163,7 +175,7 @@ boot_disk_select(struct gmesh *mesh)
}
for (i = 0; i < n; i++)
free(disks[i].text);
free((char*)disks[i].desc);
return (chosen);
}
@ -203,6 +215,9 @@ wizard_partition(struct gmesh *mesh, const char *disk)
const char *scheme = NULL;
char message[512];
int choice;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
LIST_FOREACH(classp, &mesh->lg_class, lg_class)
if (strcmp(classp->lg_name, "PART") == 0)
@ -228,22 +243,23 @@ wizard_partition(struct gmesh *mesh, const char *disk)
scheme = NULL;
query:
dialog_vars.yes_label = "Entire Disk";
dialog_vars.no_label = "Partition";
conf.button.ok_label = "Entire Disk";
conf.button.cancel_label = "Partition";
if (gpart != NULL)
dialog_vars.defaultno = TRUE;
conf.button.default_cancel = true;
snprintf(message, sizeof(message), "Would you like to use this entire "
"disk (%s) for FreeBSD or partition it to share it with other "
"operating systems? Using the entire disk will erase any data "
"currently stored there.", disk);
choice = dialog_yesno("Partition", message, 0, 0);
conf.title = "Partition";
choice = bsddialog_yesno(&conf, message, 9, 45);
dialog_vars.yes_label = NULL;
dialog_vars.no_label = NULL;
dialog_vars.defaultno = FALSE;
conf.button.ok_label = NULL;
conf.button.cancel_label = NULL;
conf.button.default_cancel = false;
if (choice == 1 && scheme != NULL && !is_scheme_bootable(scheme)) {
if (choice == BSDDIALOG_NO && scheme != NULL && !is_scheme_bootable(scheme)) {
char warning[512];
int subchoice;
@ -252,8 +268,9 @@ wizard_partition(struct gmesh *mesh, const char *disk)
"FreeBSD, it must be repartitioned. This will destroy all "
"data on the disk. Are you sure you want to proceed?",
scheme);
subchoice = dialog_yesno("Non-bootable Disk", warning, 0, 0);
if (subchoice != 0)
conf.title = "Non-bootable Disk";
subchoice = bsddialog_yesno(&conf, warning, 0, 0);
if (subchoice != BSDDIALOG_YES)
goto query;
gpart_destroy(gpart);
@ -266,9 +283,10 @@ wizard_partition(struct gmesh *mesh, const char *disk)
if (scheme == NULL || choice == 0) {
if (gpart != NULL && scheme != NULL) {
/* Erase partitioned disk */
choice = dialog_yesno("Confirmation", "This will erase "
conf.title = "Confirmation";
choice = bsddialog_yesno(&conf, "This will erase "
"the disk. Are you sure you want to proceed?", 0, 0);
if (choice != 0)
if (choice != BSDDIALOG_YES)
goto query;
gpart_destroy(gpart);
@ -307,6 +325,7 @@ wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype,
char swapsizestr[10], rootsizestr[10];
intmax_t swapsize, available;
int retval;
struct bsddialog_conf conf;
if (strcmp(fstype, "zfs") == 0) {
fsname = fsnames[1];
@ -337,11 +356,11 @@ wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype,
"to choose another disk or to open the partition editor?",
disk, availablestr, neededstr);
dialog_vars.yes_label = "Another Disk";
dialog_vars.no_label = "Editor";
retval = dialog_yesno("Warning", message, 0, 0);
dialog_vars.yes_label = NULL;
dialog_vars.no_label = NULL;
bsddialog_initconf(&conf);
conf.button.ok_label = "Another Disk";
conf.button.cancel_label = "Editor";
conf.title = "Warning";
retval = bsddialog_yesno(&conf, message, 0, 0);
return (!retval); /* Editor -> return 0 */
}

View File

@ -30,18 +30,19 @@
#include <sys/param.h>
#include <dialog.h>
#include <dlg_keys.h>
#include <bsddialog.h>
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <inttypes.h>
#include <libgeom.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "diskeditor.h"
#include "diskmenu.h"
#include "partedit.h"
struct pmetadata_head part_metadata;
@ -66,7 +67,7 @@ sigint_handler(int sig)
gpart_revert_all(&mesh);
geom_deletetree(&mesh);
end_dialog();
bsddialog_end();
exit(1);
}
@ -78,8 +79,9 @@ main(int argc, const char **argv)
const char *progname, *prompt;
struct partedit_item *items = NULL;
struct gmesh mesh;
int i, op, nitems, nscroll;
int i, op, nitems;
int error;
struct bsddialog_conf conf;
progname = getprogname();
if (strcmp(progname, "sade") == 0)
@ -89,11 +91,12 @@ main(int argc, const char **argv)
init_fstab_metadata();
init_dialog(stdin, stdout);
if (bsddialog_init() == BSDDIALOG_ERROR)
err(1, "%s", bsddialog_geterror());
bsddialog_initconf(&conf);
if (!sade_mode)
dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
dialog_vars.item_help = TRUE;
nscroll = i = 0;
bsddialog_backtitle(&conf, "FreeBSD Installer");
i = 0;
/* Revert changes on SIGINT */
signal(SIGINT, sigint_handler);
@ -111,26 +114,28 @@ main(int argc, const char **argv)
error = scripted_editor(argc, argv);
prompt = NULL;
if (error != 0) {
end_dialog();
bsddialog_end();
return (error);
}
} else {
prompt = "Create partitions for FreeBSD. No changes will be "
"made until you select Finish.";
prompt = "Create partitions for FreeBSD, F1 for help.\n"
"No changes will be made until you select Finish.";
}
/* Show the part editor either immediately, or to confirm wizard */
while (prompt != NULL) {
dlg_clear();
dlg_put_backtitle();
bsddialog_clearterminal();
if (!sade_mode)
bsddialog_backtitle(&conf, "FreeBSD Installer");
error = geom_gettree(&mesh);
if (error == 0)
items = read_geom_mesh(&mesh, &nitems);
if (error || items == NULL) {
dialog_msgbox("Error", "No disks found. If you need to "
"install a kernel driver, choose Shell at the "
"installation menu.", 0, 0, TRUE);
conf.title = "Error";
bsddialog_msgbox(&conf, "No disks found. If you need "
"to install a kernel driver, choose Shell at the "
"installation menu.", 0, 0);
break;
}
@ -138,21 +143,21 @@ main(int argc, const char **argv)
if (i >= nitems)
i = nitems - 1;
op = diskeditor_show("Partition Editor", prompt,
items, nitems, &i, &nscroll);
op = diskmenu_show("Partition Editor", prompt, items, nitems,
&i);
switch (op) {
case 0: /* Create */
case BUTTON_CREATE:
gpart_create((struct gprovider *)(items[i].cookie),
NULL, NULL, NULL, NULL, 1);
break;
case 1: /* Delete */
case BUTTON_DELETE:
gpart_delete((struct gprovider *)(items[i].cookie));
break;
case 2: /* Modify */
case BUTTON_MODIFY:
gpart_edit((struct gprovider *)(items[i].cookie));
break;
case 3: /* Revert */
case BUTTON_REVERT:
gpart_revert_all(&mesh);
while ((md = TAILQ_FIRST(&part_metadata)) != NULL) {
if (md->fstab != NULL) {
@ -172,33 +177,33 @@ main(int argc, const char **argv)
}
init_fstab_metadata();
break;
case 4: /* Auto */
case BUTTON_AUTO:
part_wizard("ufs");
break;
}
error = 0;
if (op == 5) { /* Finished */
dialog_vars.ok_label = __DECONST(char *, "Commit");
dialog_vars.extra_label =
__DECONST(char *, "Revert & Exit");
dialog_vars.extra_button = TRUE;
dialog_vars.cancel_label = __DECONST(char *, "Back");
op = dialog_yesno("Confirmation", "Your changes will "
"now be written to disk. If you have chosen to "
"overwrite existing data, it will be PERMANENTLY "
"ERASED. Are you sure you want to commit your "
"changes?", 0, 0);
dialog_vars.ok_label = NULL;
dialog_vars.extra_button = FALSE;
dialog_vars.cancel_label = NULL;
if (op == BUTTON_FINISH) {
conf.button.ok_label = "Commit";
conf.button.with_extra = true;
conf.button.extra_label = "Revert & Exit";
conf.button.cancel_label = "Back";
conf.title = "Confirmation";
op = bsddialog_yesno(&conf, "Your changes will now be "
"written to disk. If you have chosen to overwrite "
"existing data, it will be PERMANENTLY ERASED. Are "
"you sure you want to commit your changes?", 0, 0);
conf.button.ok_label = NULL;
conf.button.with_extra = false;
conf.button.extra_label = NULL;
conf.button.cancel_label = NULL;
if (op == 0 && validate_setup()) { /* Save */
if (op == BSDDIALOG_OK && validate_setup()) { /* Save */
error = apply_changes(&mesh);
if (!error)
apply_workaround(&mesh);
break;
} else if (op == 3) { /* Quit */
} else if (op == BSDDIALOG_EXTRA) { /* Quit */
gpart_revert_all(&mesh);
error = -1;
break;
@ -221,7 +226,7 @@ main(int argc, const char **argv)
geom_deletetree(&mesh);
free(items);
end_dialog();
bsddialog_end();
return (error);
}
@ -274,7 +279,8 @@ static int
validate_setup(void)
{
struct partition_metadata *md, *root = NULL;
int cancel;
int button;
struct bsddialog_conf conf;
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0)
@ -283,11 +289,14 @@ validate_setup(void)
/* XXX: Check for duplicate mountpoints */
}
bsddialog_initconf(&conf);
if (root == NULL) {
dialog_msgbox("Error", "No root partition was found. "
"The root FreeBSD partition must have a mountpoint of '/'.",
0, 0, TRUE);
return (FALSE);
conf.title = "Error";
bsddialog_msgbox(&conf, "No root partition was found. "
"The root FreeBSD partition must have a mountpoint "
"of '/'.", 0, 0);
return (false);
}
/*
@ -295,20 +304,20 @@ validate_setup(void)
* usually a mistake
*/
if (root->newfs == NULL && !sade_mode) {
dialog_vars.defaultno = TRUE;
cancel = dialog_yesno("Warning", "The chosen root partition "
conf.button.default_cancel = true;
conf.title = "Warning";
button = bsddialog_yesno(&conf, "The chosen root partition "
"has a preexisting filesystem. If it contains an existing "
"FreeBSD system, please update it with freebsd-update "
"instead of installing a new system on it. The partition "
"can also be erased by pressing \"No\" and then deleting "
"and recreating it. Are you sure you want to proceed?",
0, 0);
dialog_vars.defaultno = FALSE;
if (cancel)
return (FALSE);
if (button == BSDDIALOG_CANCEL)
return (false);
}
return (TRUE);
return (true);
}
static int
@ -332,37 +341,41 @@ apply_changes(struct gmesh *mesh)
{
struct partition_metadata *md;
char message[512];
int i, nitems, error;
const char **items;
int i, nitems, error, *miniperc;
const char **minilabel;
const char *fstab_path;
FILE *fstab;
struct bsddialog_conf conf;
nitems = 1; /* Partition table changes */
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->newfs != NULL)
nitems++;
}
items = calloc(nitems * 2, sizeof(const char *));
items[0] = "Writing partition tables";
items[1] = "7"; /* In progress */
minilabel = calloc(nitems, sizeof(const char *));
miniperc = calloc(nitems, sizeof(int));
minilabel[0] = "Writing partition tables";
miniperc[0] = BSDDIALOG_MG_INPROGRESS;
i = 1;
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->newfs != NULL) {
char *item;
item = malloc(255);
sprintf(item, "Initializing %s", md->name);
items[i*2] = item;
items[i*2 + 1] = "Pending";
minilabel[i] = item;
miniperc[i] = BSDDIALOG_MG_PENDING;
i++;
}
}
i = 0;
dialog_mixedgauge("Initializing",
"Initializing file systems. Please wait.", 0, 0, i*100/nitems,
nitems, __DECONST(char **, items));
bsddialog_initconf(&conf);
conf.title = "Initializing";
bsddialog_mixedgauge(&conf,
"Initializing file systems. Please wait.", 0, 0, i * 100 / nitems,
nitems, minilabel, miniperc);
gpart_commit(mesh);
items[i*2 + 1] = "3";
miniperc[i] = BSDDIALOG_MG_COMPLETED;
i++;
if (getenv("BSDINSTALL_LOG") == NULL)
@ -370,25 +383,27 @@ apply_changes(struct gmesh *mesh)
TAILQ_FOREACH(md, &part_metadata, metadata) {
if (md->newfs != NULL) {
items[i*2 + 1] = "7"; /* In progress */
dialog_mixedgauge("Initializing",
miniperc[i] = BSDDIALOG_MG_INPROGRESS;
bsddialog_mixedgauge(&conf,
"Initializing file systems. Please wait.", 0, 0,
i*100/nitems, nitems, __DECONST(char **, items));
i * 100 / nitems, nitems, minilabel, miniperc);
sprintf(message, "(echo %s; %s) >>%s 2>>%s",
md->newfs, md->newfs, getenv("BSDINSTALL_LOG"),
getenv("BSDINSTALL_LOG"));
error = system(message);
items[i*2 + 1] = (error == 0) ? "3" : "1";
miniperc[i] = (error == 0) ?
BSDDIALOG_MG_COMPLETED : BSDDIALOG_MG_FAILED;
i++;
}
}
dialog_mixedgauge("Initializing",
"Initializing file systems. Please wait.", 0, 0,
i*100/nitems, nitems, __DECONST(char **, items));
bsddialog_mixedgauge(&conf, "Initializing file systems. Please wait.",
0, 0, i * 100 / nitems, nitems, minilabel, miniperc);
for (i = 1; i < nitems; i++)
free(__DECONST(char *, items[i*2]));
free(items);
free(__DECONST(char *, minilabel[i]));
free(minilabel);
free(miniperc);
/* Sort filesystems for fstab so that mountpoints are ordered */
{
@ -421,7 +436,8 @@ apply_changes(struct gmesh *mesh)
if (fstab == NULL) {
sprintf(message, "Cannot open fstab file %s for writing (%s)\n",
getenv("PATH_FSTAB"), strerror(errno));
dialog_msgbox("Error", message, 0, 0, TRUE);
conf.title = "Error";
bsddialog_msgbox(&conf, message, 0, 0);
return (-1);
}
fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n");
@ -444,6 +460,7 @@ apply_workaround(struct gmesh *mesh)
struct ggeom *gp;
struct gconfig *gc;
const char *scheme = NULL, *modified = NULL;
struct bsddialog_conf conf;
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
if (strcmp(classp->lg_name, "PART") == 0)
@ -451,7 +468,9 @@ apply_workaround(struct gmesh *mesh)
}
if (strcmp(classp->lg_name, "PART") != 0) {
dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
bsddialog_initconf(&conf);
conf.title = "Error";
bsddialog_msgbox(&conf, "gpart not found!", 0, 0);
return;
}