diff options
34 files changed, 3974 insertions, 0 deletions
diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 845b675..6e77bbf 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -32,6 +32,8 @@ .. .. libexec + bsdinstall + .. lpr ru .. diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index f3e853e..6209cb5 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -7,6 +7,7 @@ SUBDIR= adduser \ arp \ bootparamd \ burncd \ + bsdinstall \ cdcontrol \ chkgrp \ chown \ diff --git a/usr.sbin/bsdinstall/Makefile b/usr.sbin/bsdinstall/Makefile new file mode 100644 index 0000000..5e39b0b --- /dev/null +++ b/usr.sbin/bsdinstall/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SUBDIR= distextract distfetch partedit scripts +SCRIPTS= bsdinstall + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/bsdinstall b/usr.sbin/bsdinstall/bsdinstall new file mode 100755 index 0000000..04162c8 --- /dev/null +++ b/usr.sbin/bsdinstall/bsdinstall @@ -0,0 +1,43 @@ +#!/bin/sh +#- +# 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$ + +: ${DISTRIBUTIONS="kernel.tgz world.tgz"}; export DISTRIBUTIONS +: ${BSDINSTALL_LOG="/tmp/bsdinstall_log"}; export BSDINSTALL_LOG +: ${BSDINSTALL_TMPETC="/tmp/bsdinstall_etc"}; export BSDINSTALL_TMPETC +: ${PATH_FSTAB="$BSDINSTALL_TMPETC/fstab"}; export PATH_FSTAB +: ${BSDINSTALL_DISTDIR="/usr/freebsd-dist"}; export BSDINSTALL_DISTDIR +: ${BSDINSTALL_CHROOT="/mnt"}; export BSDINSTALL_CHROOT + +VERB=$1; shift + +if [ -z $VERB ]; then + VERB=auto +fi + +exec /usr/libexec/bsdinstall/$VERB $@ + diff --git a/usr.sbin/bsdinstall/distextract/Makefile b/usr.sbin/bsdinstall/distextract/Makefile new file mode 100644 index 0000000..3ad1f98 --- /dev/null +++ b/usr.sbin/bsdinstall/distextract/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +BINDIR= /usr/libexec/bsdinstall +PROG= distextract +LDADD= -larchive -lncursesw -ldialog -lm + +WARNS?= 6 +NO_MAN= true + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/distextract/distextract.c b/usr.sbin/bsdinstall/distextract/distextract.c new file mode 100644 index 0000000..efd9a1b --- /dev/null +++ b/usr.sbin/bsdinstall/distextract/distextract.c @@ -0,0 +1,176 @@ +/*- + * 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 <errno.h> +#include <limits.h> +#include <archive.h> +#include <dialog.h> + +static int extract_files(int nfiles, const char **files); + +int +main(void) +{ + char *diststring = strdup(getenv("DISTRIBUTIONS")); + const char **dists; + int i, retval, ndists = 0; + for (i = 0; diststring[i] != 0; i++) + if (isspace(diststring[i]) && !isspace(diststring[i+1])) + ndists++; + ndists++; /* Last one */ + + dists = calloc(ndists, sizeof(const char *)); + for (i = 0; i < ndists; i++) + dists[i] = strsep(&diststring, " \t"); + + chdir(getenv("BSDINSTALL_CHROOT")); + retval = extract_files(ndists, dists); + + free(diststring); + free(dists); + + return (retval); +} + +static int +extract_files(int nfiles, const char **files) +{ + const char *items[nfiles*2]; + char path[PATH_MAX]; + int archive_files[nfiles]; + int total_files, current_files, archive_file; + struct archive *archive; + struct archive_entry *entry; + char errormsg[512]; + char status[8]; + int i, err, progress, last_progress; + + err = 0; + progress = 0; + + /* Make the transfer list for dialog */ + for (i = 0; i < nfiles; i++) { + items[i*2] = strrchr(files[i], '/'); + if (items[i*2] != NULL) + items[i*2]++; + else + items[i*2] = files[i]; + items[i*2 + 1] = "Pending"; + } + + init_dialog(stdin, stdout); + dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); + dlg_put_backtitle(); + dialog_msgbox("", + "Checking distribution archives.\nPlease wait...", 0, 0, FALSE); + + /* Open all the archives */ + total_files = 0; + for (i = 0; i < nfiles; i++) { + archive = archive_read_new(); + archive_read_support_format_all(archive); + archive_read_support_compression_all(archive); + sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); + err = archive_read_open_filename(archive, path, 4096); + if (err != ARCHIVE_OK) { + snprintf(errormsg, sizeof(errormsg), + "Error while extracting %s: %s\n", items[i*2], + archive_error_string(archive)); + items[i*2 + 1] = "Failed"; + dialog_msgbox("Extract Error", errormsg, 0, 0, + TRUE); + goto exit; + } + archive_files[i] = 0; + while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) + archive_files[i]++; + total_files += archive_files[i]; + archive_read_free(archive); + } + + current_files = 0; + + for (i = 0; i < nfiles; i++) { + archive = archive_read_new(); + archive_read_support_format_all(archive); + archive_read_support_compression_all(archive); + sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); + err = archive_read_open_filename(archive, path, 4096); + + items[i*2 + 1] = "In Progress"; + archive_file = 0; + + while ((err = archive_read_next_header(archive, &entry)) == + ARCHIVE_OK) { + last_progress = progress; + progress = (current_files*100)/total_files; + + sprintf(status, "-%d", + (archive_file*100)/archive_files[i]); + items[i*2 + 1] = status; + + if (progress > last_progress) + dialog_mixedgauge("Archive Extraction", + "Extracting distribution files...", 0, 0, + progress, nfiles, + __DECONST(char **, items)); + + err = archive_read_extract(archive, entry, + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | + ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); + + if (err != ARCHIVE_OK) + break; + + archive_file++; + current_files++; + } + + items[i*2 + 1] = "Done"; + + if (err != ARCHIVE_EOF) { + snprintf(errormsg, sizeof(errormsg), + "Error while extracting %s: %s\n", items[i*2], + archive_error_string(archive)); + items[i*2 + 1] = "Failed"; + dialog_msgbox("Extract Error", errormsg, 0, 0, + TRUE); + goto exit; + } + + archive_read_free(archive); + } + + err = 0; +exit: + end_dialog(); + + return (err); +} diff --git a/usr.sbin/bsdinstall/distfetch/Makefile b/usr.sbin/bsdinstall/distfetch/Makefile new file mode 100644 index 0000000..5a449ac1 --- /dev/null +++ b/usr.sbin/bsdinstall/distfetch/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +BINDIR= /usr/libexec/bsdinstall +PROG= distfetch +LDADD= -lfetch -lncursesw -ldialog -lm + +WARNS?= 6 +NO_MAN= true + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/distfetch/distfetch.c b/usr.sbin/bsdinstall/distfetch/distfetch.c new file mode 100644 index 0000000..2e1d1b3 --- /dev/null +++ b/usr.sbin/bsdinstall/distfetch/distfetch.c @@ -0,0 +1,187 @@ +/*- + * 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 <sys/param.h> +#include <stdio.h> +#include <errno.h> +#include <fetch.h> +#include <dialog.h> + +static int fetch_files(int nfiles, char **urls); + +int +main(void) +{ + char *diststring = strdup(getenv("DISTRIBUTIONS")); + char **urls; + int i, nfetched, ndists = 0; + for (i = 0; diststring[i] != 0; i++) + if (isspace(diststring[i]) && !isspace(diststring[i+1])) + ndists++; + ndists++; /* Last one */ + + urls = calloc(ndists, sizeof(const char *)); + for (i = 0; i < ndists; i++) { + urls[i] = malloc(PATH_MAX); + sprintf(urls[i], "%s/%s", getenv("BSDINSTALL_DISTSITE"), + strsep(&diststring, " \t")); + } + + chdir(getenv("BSDINSTALL_DISTDIR")); + nfetched = fetch_files(ndists, urls); + + free(diststring); + for (i = 0; i < ndists; i++) + free(urls[i]); + free(urls); + + return ((nfetched == ndists) ? 0 : 1); +} + +static int +fetch_files(int nfiles, char **urls) +{ + const char **items; + FILE *fetch_out, *file_out; + struct url_stat ustat; + off_t total_bytes, current_bytes, fsize; + char status[8]; + char errormsg[512]; + uint8_t block[4096]; + size_t chunk; + int i, progress, last_progress; + int nsuccess = 0; /* Number of files successfully downloaded */ + + progress = 0; + + /* Make the transfer list for dialog */ + items = calloc(sizeof(char *), nfiles * 2); + for (i = 0; i < nfiles; i++) { + items[i*2] = strrchr(urls[i], '/'); + if (items[i*2] != NULL) + items[i*2]++; + else + items[i*2] = urls[i]; + items[i*2 + 1] = "Pending"; + } + + init_dialog(stdin, stdout); + dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); + dlg_put_backtitle(); + + dialog_msgbox("", "Connecting to server.\nPlease wait...", 0, 0, FALSE); + + /* Try to stat all the files */ + total_bytes = 0; + for (i = 0; i < nfiles; i++) { + if (fetchStatURL(urls[i], &ustat, "") == 0 && ustat.size > 0) + total_bytes += ustat.size; + } + + current_bytes = 0; + for (i = 0; i < nfiles; i++) { + last_progress = progress; + if (total_bytes == 0) + progress = (i*100)/nfiles; + + fetchLastErrCode = 0; + fetch_out = fetchXGetURL(urls[i], &ustat, ""); + if (fetch_out == NULL) { + snprintf(errormsg, sizeof(errormsg), + "Error while fetching %s: %s\n", urls[i], + fetchLastErrString); + items[i*2 + 1] = "Failed"; + dialog_msgbox("Fetch Error", errormsg, 0, 0, + TRUE); + continue; + } + + items[i*2 + 1] = "In Progress"; + fsize = 0; + file_out = fopen(items[i*2], "w+"); + if (file_out == NULL) { + snprintf(errormsg, sizeof(errormsg), + "Error while fetching %s: %s\n", + urls[i], strerror(errno)); + items[i*2 + 1] = "Failed"; + dialog_msgbox("Fetch Error", errormsg, 0, 0, + TRUE); + fclose(fetch_out); + continue; + } + + while ((chunk = fread(block, 1, sizeof(block), fetch_out)) + > 0) { + if (fwrite(block, 1, chunk, file_out) < chunk) + break; + + current_bytes += chunk; + fsize += chunk; + + if (total_bytes > 0) { + last_progress = progress; + progress = (current_bytes*100)/total_bytes; + } + + if (ustat.size > 0) { + sprintf(status, "-%jd", (fsize*100)/ustat.size); + items[i*2 + 1] = status; + } + + if (progress > last_progress) + dialog_mixedgauge("Fetching Distribution", + "Fetching distribution files...", 0, 0, + progress, nfiles, + __DECONST(char **, items)); + } + + if (ustat.size > 0 && fsize < ustat.size) { + if (fetchLastErrCode == 0) + snprintf(errormsg, sizeof(errormsg), + "Error while fetching %s: %s\n", + urls[i], strerror(errno)); + else + snprintf(errormsg, sizeof(errormsg), + "Error while fetching %s: %s\n", + urls[i], fetchLastErrString); + items[i*2 + 1] = "Failed"; + dialog_msgbox("Fetch Error", errormsg, 0, 0, + TRUE); + } else { + items[i*2 + 1] = "Done"; + nsuccess++; + } + + fclose(fetch_out); + fclose(file_out); + } + end_dialog(); + + free(items); + return (nsuccess); +} diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile new file mode 100644 index 0000000..80d89cc --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/Makefile @@ -0,0 +1,25 @@ +# $FreeBSD$ + +BINDIR= /usr/libexec/bsdinstall +PROG= partedit +LINKS= ${BINDIR}/partedit ${BINDIR}/autopart +LDADD= -lgeom -lncursesw -lutil -ldialog -lm + +PARTEDIT_ARCH= ${MACHINE} +.if ${MACHINE} == "i386" || ${MACHINE} == "amd64" +PARTEDIT_ARCH= x86 +.endif +.if ${MACHINE} == "sun4v" +PARTEDIT_ARCH= sparc64 +.endif +.if !exists(partedit_${PARTEDIT_ARCH}.c) +PARTEDIT_ARCH= generic +.endif + +SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \ + part_wizard.c + +WARNS?= 3 +NO_MAN= true + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/partedit/diskeditor.c b/usr.sbin/bsdinstall/partedit/diskeditor.c new file mode 100644 index 0000000..c97b003 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/diskeditor.c @@ -0,0 +1,261 @@ +/*- + * 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, 8, &attr); + wmove(partitions, y, 15); + 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", "Exit", NULL }; + int x, y; + int i; + int height, width, min_width; + int partlist_height, partlist_width, min_partlist_width; + int cur_scroll = 0; + int key, fkey; + int cur_button = 0, 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 + }; + + /* + * Set up editor window. + */ + prompt = dlg_strclone(cprompt); + + min_width = 50; + height = width = 0; + partlist_height = 10; + min_partlist_width = 0; + 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", binding); + dlg_register_buttons(partitions, "partlist", buttons); + wattrset(partitions, menubox_attr); + + 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_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_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_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_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); + cur_part = cur_scroll; + goto repaint; + case DLGK_ENTER: + goto done; + default: + if (is_DLGK_MOUSE(key)) { + cur_button = key - M_EVENT; + 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); +} + diff --git a/usr.sbin/bsdinstall/partedit/diskeditor.h b/usr.sbin/bsdinstall/partedit/diskeditor.h new file mode 100644 index 0000000..f122267 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/diskeditor.h @@ -0,0 +1,47 @@ +/*- + * 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$ + */ + +#ifndef _PARTEDIT_DISKEDITOR_H +#define _PARTEDIT_DISKEDITOR_H + +#include <inttypes.h> + +struct partedit_item { + int indentation; + const char *name; + intmax_t size; + const char *type; + char *mountpoint; + + void *cookie; +}; + +int diskeditor_show(const char *title, const char *prompt, + struct partedit_item *items, int nitems, int *selected, int *scroll); + +#endif diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c new file mode 100644 index 0000000..f6fcc08 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -0,0 +1,1092 @@ +/*- + * 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 <sys/param.h> +#include <errno.h> +#include <libutil.h> +#include <inttypes.h> + +#include <libgeom.h> +#include <dialog.h> +#include <dlg_keys.h> + +#include "partedit.h" + +#define GPART_FLAGS "x" /* Do not commit changes by default */ + +static void +gpart_show_error(const char *title, const char *explanation, const char *errstr) +{ + char *errmsg; + char message[512]; + int error; + + if (explanation == NULL) + explanation = ""; + + error = strtol(errstr, &errmsg, 0); + if (errmsg != errstr) { + while (errmsg[0] == ' ') + errmsg++; + if (errmsg[0] != '\0') + sprintf(message, "%s%s. %s", explanation, + strerror(error), errmsg); + else + sprintf(message, "%s%s", explanation, strerror(error)); + } else { + sprintf(message, "%s%s", explanation, errmsg); + } + + dialog_msgbox(title, message, 0, 0, TRUE); +} + +int +gpart_partition(const char *lg_name, const char *scheme) +{ + int cancel, choice; + struct gctl_req *r; + const char *errstr; + + 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", 0 }, + {"MBR", "DOS Partitions", + "Bootable on most x86 systems", 0 }, + {"PC98", "NEC PC9801 Partition Table", + "Bootable on NEC PC9801 systems", 0 }, + {"VTOC8", "Sun VTOC8 Partition Table", + "Bootable on Sun SPARC systems", 0 }, + }; + +schememenu: + if (scheme == NULL) { + dialog_vars.default_item = __DECONST(char *, default_scheme()); + cancel = dlg_menu("Partition Scheme", + "Select a partition scheme for this volume:", 0, 0, 0, + sizeof(items) / sizeof(items[0]), items, &choice, NULL); + dialog_vars.default_item = NULL; + + if (cancel) + return (-1); + + if (!is_scheme_bootable(items[choice].name)) { + char message[512]; + 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 */ + goto schememenu; + } + + scheme = items[choice].name; + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, lg_name); + gctl_ro_param(r, "flags", -1, GPART_FLAGS); + gctl_ro_param(r, "scheme", -1, scheme); + gctl_ro_param(r, "verb", -1, "create"); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') { + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + scheme = NULL; + goto schememenu; + } + gctl_free(r); + + if (bootcode_path(scheme) != NULL) + get_part_metadata(lg_name, 1)->bootcode = 1; + return (0); +} + +static void +gpart_activate(struct gprovider *pp) +{ + struct gconfig *gc; + struct gctl_req *r; + const char *errstr, *scheme; + const char *attribute = NULL; + intmax_t idx; + + /* + * Some partition schemes need this partition to be marked 'active' + * for it to be bootable. + */ + LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + + if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "EBR") == 0 || + strcmp(scheme, "PC98") == 0) + attribute = "active"; + else + return; + + LIST_FOREACH(gc, &pp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "index") == 0) { + idx = atoi(gc->lg_val); + break; + } + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); + gctl_ro_param(r, "verb", -1, "set"); + gctl_ro_param(r, "attrib", -1, attribute); + gctl_ro_param(r, "index", sizeof(idx), &idx); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", "Error marking partition active:", + errstr); + gctl_free(r); +} + +static void +gpart_bootcode(struct ggeom *gp) +{ + const char *bootcode; + struct gconfig *gc; + struct gctl_req *r; + const char *errstr, *scheme; + uint8_t *boot; + size_t bootsize, bytes; + int bootfd; + + /* + * Write default bootcode to the newly partitioned disk, if that + * applies on this platform. + */ + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + + bootcode = bootcode_path(scheme); + if (bootcode == NULL) + return; + + bootfd = open(bootcode, O_RDONLY); + if (bootfd <= 0) { + dialog_msgbox("Bootcode Error", strerror(errno), 0, 0, + TRUE); + return; + } + + bootsize = lseek(bootfd, 0, SEEK_END); + boot = malloc(bootsize); + lseek(bootfd, 0, SEEK_SET); + bytes = 0; + while (bytes < bootsize) + bytes += read(bootfd, boot + bytes, bootsize - bytes); + close(bootfd); + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, gp->lg_name); + gctl_ro_param(r, "verb", -1, "bootcode"); + gctl_ro_param(r, "bootcode", bootsize, boot); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Bootcode Error", NULL, errstr); + gctl_free(r); + free(boot); +} + +static void +gpart_partcode(struct gprovider *pp) +{ + struct gconfig *gc; + const char *scheme; + const char *indexstr; + char message[255], command[255]; + + LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + + /* Make sure this partition scheme needs partcode on this platform */ + if (partcode_path(scheme) == NULL) + return; + + LIST_FOREACH(gc, &pp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "index") == 0) { + indexstr = gc->lg_val; + break; + } + } + + /* Shell out to gpart for partcode for now */ + sprintf(command, "gpart bootcode -p %s -i %s %s", + partcode_path(scheme), indexstr, pp->lg_geom->lg_name); + if (system(command) != 0) { + sprintf(message, "Error installing partcode on partition %s", + pp->lg_name); + dialog_msgbox("Error", message, 0, 0, TRUE); + } +} + +void +gpart_destroy(struct ggeom *lg_geom, int force) +{ + struct gprovider *pp; + struct gctl_req *r; + const char *errstr; + + /* Begin with the hosing: delete all partitions */ + LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider) + gpart_delete(pp); + + /* Now destroy the geom itself */ + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); + gctl_ro_param(r, "flags", -1, GPART_FLAGS); + gctl_ro_param(r, "verb", -1, "destroy"); + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + + /* If asked, commit the change */ + if (force) { + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); + gctl_ro_param(r, "verb", -1, "commit"); + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + } + + /* And any metadata associated with the partition scheme itself */ + delete_part_metadata(lg_geom->lg_name); +} + +void +gpart_edit(struct gprovider *pp) +{ + struct gctl_req *r; + struct gconfig *gc; + struct gconsumer *cp; + struct ggeom *geom; + const char *errstr, *oldtype, *scheme; + struct partition_metadata *md; + char sizestr[32]; + intmax_t idx; + int hadlabel, choice, junk, nitems; + unsigned i; + + DIALOG_FORMITEM items[] = { + {0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0, + FALSE, "Filesystem type (e.g. freebsd-ufs, 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}, + }; + + /* + * Find the PART geom we are manipulating. This may be a consumer of + * this provider, or its parent. Check the consumer case first. + */ + geom = NULL; + LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) + if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { + char message[512]; + /* + * The PART object is a consumer, so the user wants to + * edit the partition table. gpart doesn't really + * support this, so we have to hose the whole table + * first. + */ + + sprintf(message, "Changing the partition scheme on " + "this disk (%s) requires deleting all existing " + "partitions on this drive. This will PERMANENTLY " + "ERASE any data stored here. Are you sure you want " + "to proceed?", cp->lg_geom->lg_name); + dialog_vars.defaultno = TRUE; + choice = dialog_yesno("Warning", message, 0, 0); + dialog_vars.defaultno = FALSE; + + if (choice == 1) /* cancel */ + return; + + /* Destroy the geom and all sub-partitions */ + gpart_destroy(cp->lg_geom, 0); + + /* Now re-partition and return */ + gpart_partition(cp->lg_geom->lg_name, NULL); + return; + } + + if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) + geom = pp->lg_geom; + + if (geom == NULL) { + /* Disk not partitioned, so partition it */ + gpart_partition(pp->lg_geom->lg_name, NULL); + return; + } + + LIST_FOREACH(gc, &geom->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + + /* Labels only supported on GPT and APM */ + if (strcmp(scheme, "GPT") == 0 || strcmp(scheme, "APM") == 0) + nitems = 4; + else + nitems = 3; + + /* Edit editable parameters of a partition */ + hadlabel = 0; + 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; + } + if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) { + hadlabel = 1; + items[3].text = gc->lg_val; + } + if (strcmp(gc->lg_name, "index") == 0) + idx = atoi(gc->lg_val); + } + + 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; + break; + } + } + + humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + items[1].text = sizestr; + +editpart: + choice = dlg_form("Edit Partition", "", 0, 0, 0, nitems, items, &junk); + + if (choice) /* Cancel pressed */ + return; + + /* 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); + goto editpart; + } + + if (strncmp(items[0].text, "freebsd-", 8) != 0 && + items[0].text[0] != '\0') { + char message[512]; + + sprintf(message, "Cannot mount unknown file system %s!\n", + items[0].text); + dialog_msgbox("Error", message, 0, 0, TRUE); + goto editpart; + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, geom->lg_name); + 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); + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') { + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + goto editpart; + } + gctl_free(r); + + set_default_part_metadata(pp->lg_name, scheme, items[0].text, + items[2].text, strcmp(oldtype, items[0].text) != 0); + + for (i = 0; i < (sizeof(items) / sizeof(items[0])); i++) + if (items[i].text_free) + free(items[i].text); +} + +void +set_default_part_metadata(const char *name, const char *scheme, + const char *type, const char *mountpoint, int newfs) +{ + struct partition_metadata *md; + + /* Set part metadata */ + md = get_part_metadata(name, 1); + + if (newfs) { + if (md->newfs != NULL) { + free(md->newfs); + md->newfs = NULL; + } + + if (strcmp(type, "freebsd-ufs") == 0) { + md->newfs = malloc(255); + sprintf(md->newfs, "newfs /dev/%s", name); + } + } + + if (strcmp(type, "freebsd-swap") == 0) + mountpoint = "none"; + if (strcmp(type, "freebsd-boot") == 0) + md->bootcode = 1; + + /* VTOC8 needs partcode in UFS partitions */ + if (strcmp(scheme, "VTOC8") == 0 && strcmp(type, "freebsd-ufs") == 0) + md->bootcode = 1; + + if (mountpoint == NULL || mountpoint[0] == '\0') { + if (md->fstab != NULL) { + free(md->fstab->fs_spec); + free(md->fstab->fs_file); + free(md->fstab->fs_vfstype); + free(md->fstab->fs_mntops); + free(md->fstab->fs_type); + free(md->fstab); + md->fstab = NULL; + } + } else { + if (md->fstab == NULL) { + md->fstab = malloc(sizeof(struct fstab)); + } else { + free(md->fstab->fs_spec); + free(md->fstab->fs_file); + free(md->fstab->fs_vfstype); + free(md->fstab->fs_mntops); + free(md->fstab->fs_type); + } + md->fstab->fs_spec = malloc(strlen(name) + 6); + sprintf(md->fstab->fs_spec, "/dev/%s", name); + md->fstab->fs_file = strdup(mountpoint); + /* Get VFS from text after freebsd-, if possible */ + if (strncmp("freebsd-", type, 8)) + md->fstab->fs_vfstype = strdup(&type[8]); + else + md->fstab->fs_vfstype = strdup(type); /* Guess */ + md->fstab->fs_vfstype = strdup(&type[8]); + if (strcmp(type, "freebsd-swap") == 0) { + md->fstab->fs_type = strdup(FSTAB_SW); + md->fstab->fs_freq = 0; + md->fstab->fs_passno = 0; + } else { + md->fstab->fs_type = strdup(FSTAB_RW); + if (strcmp(mountpoint, "/") == 0) { + md->fstab->fs_freq = 1; + md->fstab->fs_passno = 1; + } else { + md->fstab->fs_freq = 2; + md->fstab->fs_passno = 2; + } + } + md->fstab->fs_mntops = strdup(md->fstab->fs_type); + } +} + +static +int part_compare(const void *xa, const void *xb) +{ + struct gprovider **a = (struct gprovider **)xa; + struct gprovider **b = (struct gprovider **)xb; + intmax_t astart, bstart; + struct gconfig *gc; + + astart = bstart = 0; + LIST_FOREACH(gc, &(*a)->lg_config, lg_config) + if (strcmp(gc->lg_name, "start") == 0) { + astart = strtoimax(gc->lg_val, NULL, 0); + break; + } + LIST_FOREACH(gc, &(*b)->lg_config, lg_config) + if (strcmp(gc->lg_name, "start") == 0) { + bstart = strtoimax(gc->lg_val, NULL, 0); + break; + } + + if (astart < bstart) + return -1; + else if (astart > bstart) + return 1; + else + return 0; +} + +intmax_t +gpart_max_free(struct ggeom *geom, intmax_t *npartstart) +{ + struct gconfig *gc; + struct gprovider *pp, **providers; + intmax_t lastend; + intmax_t start, end; + intmax_t maxsize, maxstart; + intmax_t partstart, partend; + int i, nparts; + + /* Now get the maximum free size and free start */ + start = end = 0; + LIST_FOREACH(gc, &geom->lg_config, lg_config) { + if (strcmp(gc->lg_name, "first") == 0) + start = strtoimax(gc->lg_val, NULL, 0); + if (strcmp(gc->lg_name, "last") == 0) + end = strtoimax(gc->lg_val, NULL, 0); + } + + i = nparts = 0; + LIST_FOREACH(pp, &geom->lg_provider, lg_provider) + nparts++; + providers = calloc(nparts, sizeof(providers[0])); + LIST_FOREACH(pp, &geom->lg_provider, lg_provider) + providers[i++] = pp; + qsort(providers, nparts, sizeof(providers[0]), part_compare); + + lastend = start - 1; + maxsize = 0; + for (i = 0; i < nparts; i++) { + pp = providers[i]; + + LIST_FOREACH(gc, &pp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "start") == 0) + partstart = strtoimax(gc->lg_val, NULL, 0); + if (strcmp(gc->lg_name, "end") == 0) + partend = strtoimax(gc->lg_val, NULL, 0); + } + + if (partstart - lastend > maxsize) { + maxsize = partstart - lastend - 1; + maxstart = lastend + 1; + } + + lastend = partend; + } + + if (end - lastend > maxsize) { + maxsize = end - lastend - 1; + maxstart = lastend + 1; + } + + pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; + + /* Compute beginning of new partition and maximum available space */ + if (pp->lg_stripesize > 0 && + (maxstart*pp->lg_sectorsize % pp->lg_stripesize) != 0) { + intmax_t offset = (pp->lg_stripesize - + ((maxstart*pp->lg_sectorsize) % pp->lg_stripesize)) / + pp->lg_sectorsize; + maxstart += offset; + maxsize -= offset; + } + + if (npartstart != NULL) + *npartstart = maxstart; + + return (maxsize); +} + +void +gpart_create(struct gprovider *pp, char *default_type, char *default_size, + char *default_mountpoint, char **partname, int interactive) +{ + struct gctl_req *r; + struct gconfig *gc; + struct gconsumer *cp; + struct ggeom *geom; + const char *errstr, *scheme; + char sizestr[32], startstr[32], output[64]; + intmax_t maxsize, size, sector, firstfree, stripe; + uint64_t bytes; + int nitems, choice, junk; + unsigned i; + + DIALOG_FORMITEM items[] = { + {0, "Type:", 5, 0, 0, FALSE, "freebsd-ufs", 11, 0, 12, 15, 0, + FALSE, "Filesystem type (e.g. freebsd-ufs, 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}, + }; + + if (partname != NULL) + *partname = NULL; + + /* Record sector and stripe sizes */ + sector = pp->lg_sectorsize; + stripe = pp->lg_stripesize; + + /* + * Find the PART geom we are manipulating. This may be a consumer of + * this provider, or its parent. Check the consumer case first. + */ + geom = NULL; + LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) + if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { + geom = cp->lg_geom; + break; + } + + if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) + geom = pp->lg_geom; + + /* Now get the partition scheme */ + scheme = NULL; + if (geom != NULL) { + LIST_FOREACH(gc, &geom->lg_config, lg_config) + if (strcmp(gc->lg_name, "scheme") == 0) + scheme = gc->lg_val; + } + + if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) { + if (gpart_partition(pp->lg_geom->lg_name, NULL) == 0) + dialog_msgbox("", + "The partition table has been successfully created." + " Please press Create again to create partitions.", + 0, 0, TRUE); + + return; + } + + /* + * If we still don't have a geom, either the user has + * canceled partitioning or there has been an error which has already + * been displayed, so bail. + */ + if (geom == NULL) + return; + + maxsize = size = gpart_max_free(geom, &firstfree); + if (size <= 0) { + dialog_msgbox("Error", "No free space left on device.", 0, 0, + TRUE); + return; + } + + humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + items[1].text = sizestr; + + /* Special-case the MBR default type for nested partitions */ + if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "PC98") == 0) + items[0].text = "freebsd"; + + /* Labels only supported on GPT and APM */ + if (strcmp(scheme, "GPT") == 0 || strcmp(scheme, "APM") == 0) + nitems = 4; + else + nitems = 3; + + if (default_type != NULL) + items[0].text = default_type; + if (default_size != NULL) + items[1].text = default_size; + if (default_mountpoint != NULL) + items[2].text = default_mountpoint; + +addpartform: + if (interactive) { + choice = dlg_form("Add Partition", "", 0, 0, 0, nitems, + items, &junk); + if (choice) /* Cancel pressed */ + return; + } + + size = maxsize; + if (strlen(items[1].text) > 0) { + if (expand_number(items[1].text, &bytes) != 0) { + char error[512]; + + sprintf(error, "Invalid size: %s\n", strerror(errno)); + dialog_msgbox("Error", error, 0, 0, TRUE); + 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); + goto addpartform; + } + + /* Warn if no mountpoint set */ + if (strcmp(items[0].text, "freebsd-ufs") == 0 && + items[2].text[0] != '/') { + dialog_vars.defaultno = TRUE; + choice = dialog_yesno("Warning", + "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; + if (choice == 1) /* cancel */ + goto addpartform; + } + + /* If this is the root partition, check that this scheme is bootable */ + if (strcmp(items[2].text, "/") == 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 */ + goto addpartform; + } + + /* + * If this is the root partition, and we need a boot partition, ask + * the user to add one. + */ + if (strcmp(items[2].text, "/") == 0 && bootpart_size(scheme) > 0) { + if (interactive) + choice = dialog_yesno("Boot Partition", + "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; + + if (choice == 0) { /* yes */ + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + 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, "freebsd-boot"); + snprintf(sizestr, sizeof(sizestr), "%jd", + bootpart_size(scheme) / sector); + gctl_ro_param(r, "size", -1, sizestr); + snprintf(startstr, sizeof(startstr), "%jd", firstfree); + gctl_ro_param(r, "start", -1, startstr); + gctl_rw_param(r, "output", sizeof(output), output); + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + + get_part_metadata(strtok(output, " "), 1)->bootcode = 1; + + /* Now adjust the part we are really adding forward */ + firstfree += bootpart_size(scheme) / sector; + size -= (bootpart_size(scheme) + stripe)/sector; + if (stripe > 0 && (firstfree*sector % stripe) != 0) + firstfree += (stripe - ((firstfree*sector) % + stripe)) / sector; + } + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + 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); + 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); + gctl_rw_param(r, "output", sizeof(output), output); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') { + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + goto addpartform; + } + + if (strcmp(items[0].text, "freebsd-boot") == 0) + get_part_metadata(strtok(output, " "), 1)->bootcode = 1; + else if (strcmp(items[0].text, "freebsd") == 0) + gpart_partition(strtok(output, " "), "BSD"); + else + set_default_part_metadata(strtok(output, " "), scheme, + items[0].text, items[2].text, 1); + + for (i = 0; i < (sizeof(items) / sizeof(items[0])); i++) + if (items[i].text_free) + free(items[i].text); + gctl_free(r); + + if (partname != NULL) + *partname = strdup(strtok(output, " ")); +} + +void +gpart_delete(struct gprovider *pp) +{ + struct gconfig *gc; + struct ggeom *geom; + struct gconsumer *cp; + struct gctl_req *r; + const char *errstr; + intmax_t idx; + int choice, is_partition; + + /* Is it a partition? */ + is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0); + + /* Find out if this is the root of a gpart geom */ + geom = NULL; + LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) + if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { + geom = cp->lg_geom; + break; + } + + /* Destroy all consumers */ + if (geom != NULL) { + if (is_partition) { + char message[512]; + /* + * We have to actually really delete the sub-partition + * tree so that the consumers will go away and the + * partition can be deleted. Warn the user. + */ + + sprintf(message, "Deleting this partition (%s) " + "requires deleting all existing sub-partitions. " + "This will PERMANENTLY ERASE any data stored here " + "and CANNOT BE REVERTED. Are you sure you want to " + "proceed?", cp->lg_geom->lg_name); + dialog_vars.defaultno = TRUE; + choice = dialog_yesno("Warning", message, 0, 0); + dialog_vars.defaultno = FALSE; + + if (choice == 1) /* cancel */ + return; + } + + gpart_destroy(geom, is_partition); + } + + /* + * If this is not a partition, see if that is a problem, complain if + * necessary, and return always, since we need not do anything further, + * error or no. + */ + if (!is_partition) { + if (geom == NULL) + dialog_msgbox("Error", + "Only partitions can be deleted.", 0, 0, TRUE); + return; + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, pp->lg_geom->lg_class->lg_name); + gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); + gctl_ro_param(r, "flags", -1, GPART_FLAGS); + gctl_ro_param(r, "verb", -1, "delete"); + + LIST_FOREACH(gc, &pp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "index") == 0) { + idx = atoi(gc->lg_val); + gctl_ro_param(r, "index", sizeof(idx), &idx); + break; + } + } + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') { + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + return; + } + + gctl_free(r); + + delete_part_metadata(pp->lg_name); +} + +void +gpart_revert_all(struct gmesh *mesh) +{ + struct gclass *classp; + struct gconfig *gc; + struct ggeom *gp; + struct gctl_req *r; + const char *errstr; + const char *modified; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "PART") == 0) + break; + } + + if (strcmp(classp->lg_name, "PART") != 0) { + dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); + return; + } + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + modified = "true"; /* XXX: If we don't know (kernel too old), + * assume there are modifications. */ + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "modified") == 0) { + modified = gc->lg_val; + break; + } + } + + if (strcmp(modified, "false") == 0) + continue; + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, gp->lg_name); + gctl_ro_param(r, "verb", -1, "undo"); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + } +} + +void +gpart_commit(struct gmesh *mesh) +{ + struct partition_metadata *md; + struct gclass *classp; + struct ggeom *gp; + struct gconfig *gc; + struct gconsumer *cp; + struct gprovider *pp; + struct gctl_req *r; + const char *errstr; + const char *modified; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "PART") == 0) + break; + } + + if (strcmp(classp->lg_name, "PART") != 0) { + dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); + return; + } + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + modified = "true"; /* XXX: If we don't know (kernel too old), + * assume there are modifications. */ + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "modified") == 0) { + modified = gc->lg_val; + break; + } + } + + if (strcmp(modified, "false") == 0) + continue; + + /* Add bootcode if necessary, before the commit */ + md = get_part_metadata(gp->lg_name, 0); + if (md != NULL && md->bootcode) + gpart_bootcode(gp); + + /* Now install partcode on its partitions, if necessary */ + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + md = get_part_metadata(pp->lg_name, 0); + if (md == NULL || !md->bootcode) + continue; + + /* Mark this partition active if that's required */ + gpart_activate(pp); + + /* Check if the partition has sub-partitions */ + LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) + if (strcmp(cp->lg_geom->lg_class->lg_name, + "PART") == 0) + break; + + if (cp == NULL) /* No sub-partitions */ + gpart_partcode(pp); + } + + r = gctl_get_handle(); + gctl_ro_param(r, "class", -1, "PART"); + gctl_ro_param(r, "arg0", -1, gp->lg_name); + gctl_ro_param(r, "verb", -1, "commit"); + + errstr = gctl_issue(r); + if (errstr != NULL && errstr[0] != '\0') + gpart_show_error("Error", NULL, errstr); + gctl_free(r); + } +} + diff --git a/usr.sbin/bsdinstall/partedit/part_wizard.c b/usr.sbin/bsdinstall/partedit/part_wizard.c new file mode 100644 index 0000000..e18293a --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/part_wizard.c @@ -0,0 +1,344 @@ +/*- + * 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 <sys/param.h> +#include <errno.h> +#include <libutil.h> +#include <inttypes.h> + +#include <libgeom.h> +#include <dialog.h> +#include <dlg_keys.h> + +#include "partedit.h" + +#define MIN_FREE_SPACE (1024*1024*1024) /* 1 GB */ +#define SWAP_SIZE(available) MIN(available/20, 4*1024*1024*1024LL) + +static char *boot_disk(struct gmesh *mesh); +static char *wizard_partition(struct gmesh *mesh, const char *disk); +static int wizard_makeparts(struct gmesh *mesh, const char *disk); + +int +part_wizard(void) { + int error; + struct gmesh mesh; + char *disk, *schemeroot; + +startwizard: + error = geom_gettree(&mesh); + + dlg_put_backtitle(); + error = geom_gettree(&mesh); + disk = boot_disk(&mesh); + if (disk == NULL) + return (1); + + dlg_clear(); + dlg_put_backtitle(); + schemeroot = wizard_partition(&mesh, disk); + free(disk); + if (schemeroot == NULL) + return (1); + + geom_deletetree(&mesh); + dlg_clear(); + dlg_put_backtitle(); + error = geom_gettree(&mesh); + + error = wizard_makeparts(&mesh, schemeroot); + if (error) + goto startwizard; + free(schemeroot); + + geom_deletetree(&mesh); + + return (0); +} + +static char * +boot_disk(struct gmesh *mesh) +{ + struct gclass *classp; + struct gconfig *gc; + struct ggeom *gp; + struct gprovider *pp; + DIALOG_LISTITEM *disks = NULL; + const char *type; + char diskdesc[512]; + char *chosen; + int i, err, selected, n = 0; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "DISK") != 0 && + strcmp(classp->lg_name, "MD") != 0) + continue; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (LIST_EMPTY(&gp->lg_provider)) + continue; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + type = NULL; + LIST_FOREACH(gc, &pp->lg_config, lg_config) + if (strcmp(gc->lg_name, "type") == 0) + type = gc->lg_val; + + /* Skip swap-backed md devices */ + if (strcmp(classp->lg_name, "MD") == 0 && + type != NULL && strcmp(type, "swap") == 0) + continue; + + disks = realloc(disks, (++n)*sizeof(disks[0])); + disks[n-1].name = pp->lg_name; + humanize_number(diskdesc, 7, pp->lg_mediasize, + "B", HN_AUTOSCALE, HN_DECIMAL); + if (strncmp(pp->lg_name, "ad", 2) == 0) + strcat(diskdesc, " ATA Hard Disk"); + else if (strncmp(pp->lg_name, "da", 2) == 0) + strcat(diskdesc, " SCSI Hard Disk"); + else if (strncmp(pp->lg_name, "md", 2) == 0) + strcat(diskdesc, " Memory Disk"); + else if (strncmp(pp->lg_name, "cd", 2) == 0) { + n--; + continue; + } + disks[n-1].text = strdup(diskdesc); + disks[n-1].help = NULL; + disks[n-1].state = 0; + } + } + } + + if (n > 1) { + err = dlg_menu("Partitioning", + "Select the disk on which to install FreeBSD.", 0, 0, 0, + n, disks, &selected, NULL); + + chosen = (err == 0) ? strdup(disks[selected].name) : NULL; + } else if (n == 1) { + chosen = strdup(disks[0].name); + } else { + chosen = NULL; + } + + for (i = 0; i < n; i++) + free(disks[i].text); + + return (chosen); +} + +static struct gprovider * +provider_for_name(struct gmesh *mesh, const char *name) +{ + struct gclass *classp; + struct gprovider *pp = NULL; + struct ggeom *gp; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "DISK") != 0 && + strcmp(classp->lg_name, "PART") != 0 && + strcmp(classp->lg_name, "MD") != 0) + continue; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (LIST_EMPTY(&gp->lg_provider)) + continue; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) + if (strcmp(pp->lg_name, name) == 0) + break; + + if (pp != NULL) break; + } + + if (pp != NULL) break; + } + + return (pp); +} + +static char * +wizard_partition(struct gmesh *mesh, const char *disk) +{ + struct gclass *classp; + struct ggeom *gpart = NULL; + struct gconfig *gc; + char message[512]; + const char *scheme = NULL; + char *retval = NULL; + int choice; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) + if (strcmp(classp->lg_name, "PART") == 0) + break; + + if (classp != NULL) { + LIST_FOREACH(gpart, &classp->lg_geom, lg_geom) + if (strcmp(gpart->lg_name, disk) == 0) + break; + } + + if (gpart != NULL) { + LIST_FOREACH(gc, &gpart->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + } + +query: + dialog_vars.yes_label = "Entire Disk"; + dialog_vars.no_label = "Partition"; + if (gpart != NULL) + dialog_vars.defaultno = 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); + + dialog_vars.yes_label = NULL; + dialog_vars.no_label = NULL; + dialog_vars.defaultno = FALSE; + + if (choice == 1 && scheme != NULL && !is_scheme_bootable(scheme)) { + char warning[512]; + int subchoice; + + sprintf(warning, "The existing partition scheme on this " + "disk (%s) is not bootable on this platform. To install " + "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) + goto query; + + gpart_destroy(gpart, 1); + gpart_partition(disk, default_scheme()); + scheme = default_scheme(); + } + + if (scheme == NULL || strcmp(scheme, "(none)") == 0 || choice == 0) { + if (gpart != NULL) { /* Erase partitioned disk */ + choice = dialog_yesno("Confirmation", "This will erase " + "the disk. Are you sure you want to proceed?", 0, 0); + if (choice != 0) + goto query; + + gpart_destroy(gpart, 1); + } + + gpart_partition(disk, default_scheme()); + scheme = default_scheme(); + } + + if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) { + struct gmesh submesh; + geom_gettree(&submesh); + gpart_create(provider_for_name(&submesh, disk), + "freebsd", NULL, NULL, &retval, + choice /* Non-interactive for "Entire Disk" */); + geom_deletetree(&submesh); + } else { + retval = strdup(disk); + } + + return (retval); +} + +static int +wizard_makeparts(struct gmesh *mesh, const char *disk) +{ + struct gmesh submesh; + struct gclass *classp; + struct ggeom *gp; + struct gconfig *gc; + const char *scheme; + struct gprovider *pp; + intmax_t swapsize, available; + char swapsizestr[10], rootsizestr[10]; + int retval; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) + if (strcmp(classp->lg_name, "PART") == 0) + break; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) + if (strcmp(gp->lg_name, disk) == 0) + break; + + LIST_FOREACH(gc, &gp->lg_config, lg_config) + if (strcmp(gc->lg_name, "scheme") == 0) + scheme = gc->lg_val; + + pp = provider_for_name(mesh, disk); + + available = gpart_max_free(gp, NULL)*pp->lg_sectorsize; + if (available < MIN_FREE_SPACE) { + char availablestr[10], neededstr[10], message[512]; + humanize_number(availablestr, 7, available, "B", HN_AUTOSCALE, + HN_DECIMAL); + humanize_number(neededstr, 7, MIN_FREE_SPACE, "B", HN_AUTOSCALE, + HN_DECIMAL); + sprintf(message, "There is not enough free space on %s to " + "install FreeBSD (%s free, %s required). Would you like " + "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; + + return (!retval); /* Editor -> return 0 */ + } + + swapsize = SWAP_SIZE(available); + humanize_number(swapsizestr, 7, swapsize, "B", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + humanize_number(rootsizestr, 7, available - swapsize - 1024*1024, + "B", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); + + geom_gettree(&submesh); + pp = provider_for_name(&submesh, disk); + gpart_create(pp, "freebsd-ufs", rootsizestr, "/", NULL, 0); + geom_deletetree(&submesh); + + geom_gettree(&submesh); + pp = provider_for_name(&submesh, disk); + gpart_create(pp, "freebsd-swap", swapsizestr, NULL, NULL, 0); + geom_deletetree(&submesh); + + return (0); +} + diff --git a/usr.sbin/bsdinstall/partedit/partedit.c b/usr.sbin/bsdinstall/partedit/partedit.c new file mode 100644 index 0000000..cb3c018 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit.c @@ -0,0 +1,445 @@ +/*- + * 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 <sys/param.h> +#include <libgen.h> +#include <libutil.h> +#include <inttypes.h> +#include <errno.h> + +#include <fstab.h> +#include <libgeom.h> +#include <dialog.h> +#include <dlg_keys.h> + +#include "diskeditor.h" +#include "partedit.h" + +struct pmetadata_head part_metadata; + +static int apply_changes(struct gmesh *mesh); +static struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems); +static void add_geom_children(struct ggeom *gp, int recurse, + struct partedit_item **items, int *nitems); +static void init_fstab_metadata(void); +static void get_mount_points(struct partedit_item *items, int nitems); +static int validate_setup(void); + +int +main(int argc, const char **argv) { + struct partition_metadata *md; + const char *prompt; + struct partedit_item *items; + struct gmesh mesh; + int i, op, nitems, nscroll; + int error; + + TAILQ_INIT(&part_metadata); + + init_fstab_metadata(); + + init_dialog(stdin, stdout); + if (strcmp(basename(argv[0]), "sade") != 0) + dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); + dialog_vars.item_help = TRUE; + nscroll = i = 0; + + if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */ + prompt = "Please review the disk setup. When complete, press " + "the Exit button."; + part_wizard(); + } else { + prompt = "Create partitions for FreeBSD. No changes will be " + "made until you select Exit."; + } + + /* Show the part editor either immediately, or to confirm wizard */ + while (1) { + error = geom_gettree(&mesh); + items = read_geom_mesh(&mesh, &nitems); + get_mount_points(items, nitems); + dlg_clear(); + dlg_put_backtitle(); + + if (i >= nitems) + i = nitems - 1; + op = diskeditor_show("Partition Editor", prompt, + items, nitems, &i, &nscroll); + + switch (op) { + case 0: /* Create */ + gpart_create((struct gprovider *)(items[i].cookie), + NULL, NULL, NULL, NULL, 1); + break; + case 1: /* Delete */ + gpart_delete((struct gprovider *)(items[i].cookie)); + break; + case 2: /* Modify */ + gpart_edit((struct gprovider *)(items[i].cookie)); + break; + case 3: /* Revert */ + gpart_revert_all(&mesh); + while ((md = TAILQ_FIRST(&part_metadata)) != NULL) { + if (md->fstab != NULL) { + free(md->fstab->fs_spec); + free(md->fstab->fs_file); + free(md->fstab->fs_vfstype); + free(md->fstab->fs_mntops); + free(md->fstab->fs_type); + free(md->fstab); + } + if (md->newfs != NULL) + free(md->newfs); + free(md->name); + + TAILQ_REMOVE(&part_metadata, md, metadata); + free(md); + } + init_fstab_metadata(); + break; + case 4: /* Auto */ + part_wizard(); + break; + } + + error = 0; + if (op == 5 && validate_setup()) { /* Finished */ + dialog_vars.extra_button = TRUE; + dialog_vars.extra_label = + __DECONST(char *, "Abort"); + dialog_vars.ok_label = __DECONST(char *, "Save"); + 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 proceed?", 0, 0); + dialog_vars.extra_button = FALSE; + dialog_vars.ok_label = NULL; + + if (op == 0) { /* Save */ + error = apply_changes(&mesh); + break; + } else if (op == 3) { /* Don't save => Quit */ + gpart_revert_all(&mesh); + error = -1; + break; + } + } + + geom_deletetree(&mesh); + free(items); + } + + + geom_deletetree(&mesh); + free(items); + end_dialog(); + + return (error); +} + +struct partition_metadata * +get_part_metadata(const char *name, int create) +{ + struct partition_metadata *md; + + TAILQ_FOREACH(md, &part_metadata, metadata) + if (md->name != NULL && strcmp(md->name, name) == 0) + break; + + if (md == NULL && create) { + md = calloc(1, sizeof(*md)); + md->name = strdup(name); + TAILQ_INSERT_TAIL(&part_metadata, md, metadata); + } + + return (md); +} + +void +delete_part_metadata(const char *name) { + struct partition_metadata *md; + + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->name != NULL && strcmp(md->name, name) == 0) { + if (md->fstab != NULL) { + free(md->fstab->fs_spec); + free(md->fstab->fs_file); + free(md->fstab->fs_vfstype); + free(md->fstab->fs_mntops); + free(md->fstab->fs_type); + free(md->fstab); + } + if (md->newfs != NULL) + free(md->newfs); + free(md->name); + + TAILQ_REMOVE(&part_metadata, md, metadata); + free(md); + break; + } + } +} + +static int +validate_setup(void) +{ + struct partition_metadata *md; + int root_found = FALSE; + + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) + root_found = TRUE; + + /* XXX: Check for duplicate mountpoints */ + } + + if (!root_found) { + dialog_msgbox("Error", "No root partition was found. " + "The root FreeBSD partition must have a mountpoint of '/'.", + 0, 0, TRUE); + return (FALSE); + } + + return (TRUE); +} + +static int +apply_changes(struct gmesh *mesh) +{ + struct partition_metadata *md; + char message[512]; + int i, nitems, error; + const char **items; + const char *fstab_path; + FILE *fstab; + + 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 */ + 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"; + i++; + } + } + + i = 0; + dialog_mixedgauge("Initializing", + "Initializing file systems. Please wait.", 0, 0, i*100/nitems, + nitems, __DECONST(char **, items)); + gpart_commit(mesh); + items[i*2 + 1] = "3"; + i++; + + if (getenv("BSDINSTALL_LOG") == NULL) + setenv("BSDINSTALL_LOG", "/dev/null", 1); + + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->newfs != NULL) { + items[i*2 + 1] = "7"; /* In progress */ + dialog_mixedgauge("Initializing", + "Initializing file systems. Please wait.", 0, 0, + i*100/nitems, nitems, __DECONST(char **, items)); + 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"; + i++; + } + } + dialog_mixedgauge("Initializing", + "Initializing file systems. Please wait.", 0, 0, + i*100/nitems, nitems, __DECONST(char **, items)); + + for (i = 1; i < nitems; i++) + free(__DECONST(char *, items[i*2])); + free(items); + + if (getenv("PATH_FSTAB") != NULL) + fstab_path = getenv("PATH_FSTAB"); + else + fstab_path = "/etc/fstab"; + fstab = fopen(fstab_path, "w+"); + 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); + return (-1); + } + fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n"); + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->fstab != NULL) + fprintf(fstab, "%s\t%s\t%s\t%s\t%d\t%d\n", + md->fstab->fs_spec, md->fstab->fs_file, + md->fstab->fs_vfstype, md->fstab->fs_mntops, + md->fstab->fs_freq, md->fstab->fs_passno); + } + fclose(fstab); + + return (0); +} + +static struct partedit_item * +read_geom_mesh(struct gmesh *mesh, int *nitems) { + struct gclass *classp; + struct ggeom *gp; + struct partedit_item *items; + + *nitems = 0; + items = NULL; + + /* + * Build the device table. First add all disks (and CDs). + */ + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "DISK") != 0 && + strcmp(classp->lg_name, "MD") != 0) + continue; + + /* Now recurse into all children */ + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) + add_geom_children(gp, 0, &items, nitems); + } + + return (items); +} + +static void +add_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items, + int *nitems) { + struct gconsumer *cp; + struct gprovider *pp; + struct gconfig *gc; + + if (strcmp(gp->lg_class->lg_name, "PART") == 0 && + !LIST_EMPTY(&gp->lg_config)) { + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) + (*items)[*nitems-1].type = gc->lg_val; + } + } + + if (LIST_EMPTY(&gp->lg_provider)) + return; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + if (strcmp(gp->lg_class->lg_name, "LABEL") == 0) + continue; + + /* Skip WORM media */ + if (strncmp(pp->lg_name, "cd", 2) == 0) + continue; + + *items = realloc(*items, + (*nitems+1)*sizeof(struct partedit_item)); + (*items)[*nitems].indentation = recurse; + (*items)[*nitems].name = pp->lg_name; + (*items)[*nitems].size = pp->lg_mediasize; + (*items)[*nitems].mountpoint = NULL; + (*items)[*nitems].type = ""; + (*items)[*nitems].cookie = pp; + + LIST_FOREACH(gc, &pp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "type") == 0) + (*items)[*nitems].type = gc->lg_val; + } + + /* Skip swap-backed MD devices */ + if (strcmp(gp->lg_class->lg_name, "MD") == 0 && + strcmp((*items)[*nitems].type, "swap") == 0) + continue; + + (*nitems)++; + + LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) + add_geom_children(cp->lg_geom, recurse+1, items, + nitems); + + /* Only use first provider for acd */ + if (strcmp(gp->lg_class->lg_name, "ACD") == 0) + break; + } +} + +static void +init_fstab_metadata(void) +{ + struct fstab *fstab; + struct partition_metadata *md; + + setfsent(); + while ((fstab = getfsent()) != NULL) { + md = calloc(1, sizeof(struct partition_metadata)); + + md->name = NULL; + if (strncmp(fstab->fs_spec, "/dev/", 5) == 0) + md->name = strdup(&fstab->fs_spec[5]); + + md->fstab = malloc(sizeof(struct fstab)); + md->fstab->fs_spec = strdup(fstab->fs_spec); + md->fstab->fs_file = strdup(fstab->fs_file); + md->fstab->fs_vfstype = strdup(fstab->fs_vfstype); + md->fstab->fs_mntops = strdup(fstab->fs_mntops); + md->fstab->fs_type = strdup(fstab->fs_type); + md->fstab->fs_freq = fstab->fs_freq; + md->fstab->fs_passno = fstab->fs_passno; + + md->newfs = NULL; + + TAILQ_INSERT_TAIL(&part_metadata, md, metadata); + } +} + +static void +get_mount_points(struct partedit_item *items, int nitems) +{ + struct partition_metadata *md; + int i; + + for (i = 0; i < nitems; i++) { + TAILQ_FOREACH(md, &part_metadata, metadata) { + if (md->name != NULL && md->fstab != NULL && + strcmp(md->name, items[i].name) == 0) { + items[i].mountpoint = md->fstab->fs_file; + break; + } + } + } +} diff --git a/usr.sbin/bsdinstall/partedit/partedit.h b/usr.sbin/bsdinstall/partedit/partedit.h new file mode 100644 index 0000000..6176d68 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit.h @@ -0,0 +1,80 @@ +/*- + * 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$ + */ + +#ifndef _PARTEDIT_PARTEDIT_H +#define _PARTEDIT_PARTEDIT_H + +#include <sys/queue.h> +#include <inttypes.h> +#include <fstab.h> + +struct gprovider; +struct gmesh; +struct ggeom; + +TAILQ_HEAD(pmetadata_head, partition_metadata); +extern struct pmetadata_head part_metadata; + +struct partition_metadata { + char *name; /* name of this partition, as in GEOM */ + + struct fstab *fstab; /* fstab data for this partition */ + char *newfs; /* shell command to initialize partition */ + + int bootcode; + + TAILQ_ENTRY(partition_metadata) metadata; +}; + +struct partition_metadata *get_part_metadata(const char *name, int create); +void delete_part_metadata(const char *name); + +int part_wizard(void); + +/* gpart operations */ +void gpart_delete(struct gprovider *pp); +void gpart_destroy(struct ggeom *lg_geom, int force); +void gpart_edit(struct gprovider *pp); +void gpart_create(struct gprovider *pp, char *default_type, char *default_size, + char *default_mountpoint, char **output, int interactive); +intmax_t gpart_max_free(struct ggeom *gp, intmax_t *start); +void gpart_revert(struct gprovider *pp); +void gpart_revert_all(struct gmesh *mesh); +void gpart_commit(struct gmesh *mesh); +int gpart_partition(const char *lg_name, const char *scheme); +void set_default_part_metadata(const char *name, const char *scheme, + const char *type, const char *mountpoint, int newfs); + +/* machine-dependent bootability checks */ +const char *default_scheme(void); +int is_scheme_bootable(const char *part_type); +size_t bootpart_size(const char *part_type); +const char *bootcode_path(const char *part_type); +const char *partcode_path(const char *part_type); + +#endif diff --git a/usr.sbin/bsdinstall/partedit/partedit_generic.c b/usr.sbin/bsdinstall/partedit/partedit_generic.c new file mode 100644 index 0000000..96faafa --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit_generic.c @@ -0,0 +1,69 @@ +/*- + * 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 <string.h> + +#include "partedit.h" + +const char * +default_scheme(void) { + /* + * Our loader can parse GPT, so pick that as the default for lack of + * a better idea. + */ + + return ("GPT"); +} + +int +is_scheme_bootable(const char *part_type) { + /* + * We don't know anything about this platform, so don't irritate the + * user by claiming the chosen partition scheme isn't bootable. + */ + + return (1); +} + +/* No clue => no boot partition, bootcode, or partcode */ + +size_t +bootpart_size(const char *part_type) { + return (0); +} + +const char * +bootcode_path(const char *part_type) { + return (NULL); +} + +const char * +partcode_path(const char *part_type) { + return (NULL); +} + diff --git a/usr.sbin/bsdinstall/partedit/partedit_pc98.c b/usr.sbin/bsdinstall/partedit/partedit_pc98.c new file mode 100644 index 0000000..ec438f6 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit_pc98.c @@ -0,0 +1,69 @@ +/*- + * 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 <string.h> + +#include "partedit.h" + +const char * +default_scheme(void) { + return ("PC98"); +} + +int +is_scheme_bootable(const char *part_type) { + if (strcmp(part_type, "BSD") == 0) + return (1); + if (strcmp(part_type, "PC98") == 0) + return (1); + + return (0); +} + +size_t +bootpart_size(const char *part_type) { + /* No boot partition */ + return (0); +} + +const char * +bootcode_path(const char *part_type) { + if (strcmp(part_type, "PC98") == 0) + return ("/boot/pc98boot"); + if (strcmp(part_type, "BSD") == 0) + return ("/boot/boot"); + + return (NULL); +} + +const char * +partcode_path(const char *part_type) { + /* No partcode */ + return (NULL); +} + diff --git a/usr.sbin/bsdinstall/partedit/partedit_powerpc.c b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c new file mode 100644 index 0000000..23bd8b6 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c @@ -0,0 +1,63 @@ +/*- + * 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 <string.h> + +#include "partedit.h" + +const char * +default_scheme(void) { + return ("APM"); +} + +int +is_scheme_bootable(const char *part_type) { + if (strcmp(part_type, "APM") == 0) + return (1); + return (0); +} + +size_t +bootpart_size(const char *part_type) { + if (strcmp(part_type, "APM") == 0) + return (800*1024); + return (0); +} + +const char * +bootcode_path(const char *part_type) { + return (NULL); +} + +const char * +partcode_path(const char *part_type) { + if (strcmp(part_type, "APM") == 0) + return ("/boot/boot1.hfs"); + return (NULL); +} + diff --git a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c new file mode 100644 index 0000000..b8ee052 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c @@ -0,0 +1,63 @@ +/*- + * 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 <string.h> + +#include "partedit.h" + +const char * +default_scheme(void) { + return ("VTOC8"); +} + +int +is_scheme_bootable(const char *part_type) { + if (strcmp(part_type, "VTOC8") == 0) + return (1); + return (0); +} + +size_t +bootpart_size(const char *part_type) { + /* No standalone boot partition */ + + return (0); +} + +const char * +bootcode_path(const char *part_type) { + return (NULL); +} + +const char * +partcode_path(const char *part_type) { + if (strcmp(part_type, "VTOC8") == 0) + return ("/boot/boot1"); + return (NULL); +} + diff --git a/usr.sbin/bsdinstall/partedit/partedit_x86.c b/usr.sbin/bsdinstall/partedit/partedit_x86.c new file mode 100644 index 0000000..a03a7a7 --- /dev/null +++ b/usr.sbin/bsdinstall/partedit/partedit_x86.c @@ -0,0 +1,79 @@ +/*- + * 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 <string.h> + +#include "partedit.h" + +const char * +default_scheme(void) { + return ("GPT"); +} + +int +is_scheme_bootable(const char *part_type) { + if (strcmp(part_type, "BSD") == 0) + return (1); + if (strcmp(part_type, "GPT") == 0) + return (1); + if (strcmp(part_type, "MBR") == 0) + return (1); + + return (0); +} + +size_t +bootpart_size(const char *part_type) { + if (strcmp(part_type, "GPT") == 0) + return (64*1024); + + /* No partcode except for GPT */ + return (0); +} + +const char * +bootcode_path(const char *part_type) { + if (strcmp(part_type, "GPT") == 0) + return ("/boot/pmbr"); + if (strcmp(part_type, "MBR") == 0) + return ("/boot/mbr"); + if (strcmp(part_type, "BSD") == 0) + return ("/boot/boot"); + + return (NULL); +} + +const char * +partcode_path(const char *part_type) { + if (strcmp(part_type, "GPT") == 0) + return ("/boot/gptboot"); + + /* No partcode except for GPT */ + return (NULL); +} + diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile new file mode 100644 index 0000000..d68ea5a --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +SCRIPTS= auto adduser config hostname jail keymap mount netconfig rootpass \ + services time umount wlanconfig +BINDIR= /usr/libexec/bsdinstall + +NO_MAN= true + +.include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/scripts/adduser b/usr.sbin/bsdinstall/scripts/adduser new file mode 100755 index 0000000..35c50ed --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/adduser @@ -0,0 +1,34 @@ +#!/bin/sh +#- +# 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$ + +clear +echo "FreeBSD Installer" +echo "========================" +echo "Add Users" +echo +chroot $BSDINSTALL_CHROOT adduser diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto new file mode 100755 index 0000000..5fc8f0e --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/auto @@ -0,0 +1,192 @@ +#!/bin/sh +#- +# 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$ + +echo "Begun Installation at $(date)" > $BSDINSTALL_LOG + +error() { + dialog --backtitle "FreeBSD Installer" --title "Abort" \ + --no-label "Exit" --yes-label "Restart" --yesno \ + "An installation step has been aborted. Would you like to restart the installation or exit the installer?" 0 0 + if [ $? -ne 0 ]; then + exit + else + test -f $PATH_FSTAB && bsdinstall umount + exec $0 + fi +} + + +rm -rf $BSDINSTALL_TMPETC +mkdir $BSDINSTALL_TMPETC + +trap true SIGINT # This section is optional +bsdinstall keymap + +trap error SIGINT # Catch cntrl-C here +bsdinstall hostname || error + +FETCH_DISTRIBUTIONS="" +for dist in $DISTRIBUTIONS; do + if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then + FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist" + fi +done + +if [ ! -z "$FETCH_DISTRIBUTIONS" -a ! -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle "FreeBSD Installer" --title "Network Installation" --msgbox "No installation files were found on the boot volume. The next few screens will allow you to configure networking so that they can be downloaded from the Internet." 0 0 + bsdinstall netconfig || error + NETCONFIG_DONE=yes +fi + +rm $PATH_FSTAB +touch $PATH_FSTAB + +dialog --backtitle "FreeBSD Installer" --title "Partitioning" --extra-button \ + --extra-label "Manual" --ok-label "Guided" --cancel-label "Shell" \ + --yesno "Would you like to use the guided partitioning tool (recommended for beginners) or to set up partitions manually (experts)? You can also open a shell and set up partitions entirely by hand." 0 0 + +case $? in +0) # Guided + bsdinstall autopart || error + bsdinstall mount || error + ;; +1) # Shell + clear + echo "Use this shell to set up partitions for the new system. When finished, mount the system at $BSDINSTALL_CHROOT and place an fstab file for the new system at $PATH_FSTAB. Then type 'exit'. You can also enter the partition editor at any time by entering 'bsdinstall partedit'." + sh + ;; +3) # Manual + bsdinstall partedit || error + bsdinstall mount || error + ;; +*) + error + ;; +esac + +if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then + ALL_DISTRIBUTIONS="$DISTRIBUTIONS" + + # Download to a directory in the new system as scratch space + BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/bsdinstall-dist" + mkdir -p "$BSDINSTALL_FETCHDEST" || error + + export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS" + # Try to use any existing distfiles + [ -d $BSDINSTALL_DISTDIR -a "$FETCH_DISTRIBUTIONS" != "$ALL_DISTRIBUTIONS" ] && mount_unionfs "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR" + + # Otherwise, fetch everything + if [ $? -ne 0 ]; then + export DISTRIBUTIONS="$ALL_DISTRIBUTIONS" + export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST" + fi + + bsdinstall distfetch || error + export DISTRIBUTIONS="$ALL_DISTRIBUTIONS" +fi + +bsdinstall distextract || error +bsdinstall rootpass || error + +trap true SIGINT # This section is optional +if [ "$NETCONFIG_DONE" != yes ]; then + bsdinstall netconfig # Don't check for errors -- the user may cancel +fi +bsdinstall time +bsdinstall services + +dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \ + "Would you like to add users to the installed system now?" 0 0 && \ + bsdinstall adduser + +finalconfig() { + exec 3>&1 + REVISIT=$(dialog --backtitle "FreeBSD Installer" \ + --title "Final Configuration" --no-cancel --menu \ + "Setup of your FreeBSD system is nearly complete. You can now modify your configuration choices or apply more complex changes using a shell." 0 0 0 \ + "Add User" "Add a user to the system" \ + "Root Password" "Change root password" \ + "Hostname" "Set system hostname" \ + "Network" "Networking configuration" \ + "Services" "Set daemons to run on startup" \ + "Time Zone" "Set system timezone" \ + "Shell" "Open a shell in the new system" \ + "Reboot" "Apply configuration and reboot" 2>&1 1>&3) + exec 3>&- + + case "$REVISIT" in + "Add User") + bsdinstall adduser + finalconfig + ;; + "Root Password") + bsdinstall rootpass + finalconfig + ;; + "Hostname") + bsdinstall hostname + finalconfig + ;; + "Network") + bsdinstall netconfig + finalconfig + ;; + "Services") + bsdinstall services + finalconfig + ;; + "Time Zone") + bsdinstall time + finalconfig + ;; + "Shell") + clear + echo This shell is operating in a chroot in the new system. \ + When finished making configuration changes, type \"exit\". + chroot "$BSDINSTALL_CHROOT" /bin/sh + # Don't hose local rc.conf changes + cp $BSDINSTALL_CHROOT/etc/rc.conf $BSDINSTALL_TMPETC/rc.conf.manual + finalconfig + ;; + esac +} + +# Allow user to change his mind +finalconfig + +trap error SIGINT # SIGINT is bad again +bsdinstall config || error + +if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then + [ "$BSDINSTALL_FETCHDEST" != "$BSDINSTALL_DISTDIR" ] && \ + umount "$BSDINSTALL_DISTDIR" + rm -rf "$BSDINSTALL_FETCHDEST" +fi + +echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG + diff --git a/usr.sbin/bsdinstall/scripts/config b/usr.sbin/bsdinstall/scripts/config new file mode 100755 index 0000000..5d7c3ce --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/config @@ -0,0 +1,32 @@ +#!/bin/sh +#- +# 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$ + +cat $BSDINSTALL_TMPETC/rc.conf.* >> $BSDINSTALL_TMPETC/rc.conf +rm $BSDINSTALL_TMPETC/rc.conf.* + +cp $BSDINSTALL_TMPETC/* $BSDINSTALL_CHROOT/etc diff --git a/usr.sbin/bsdinstall/scripts/hostname b/usr.sbin/bsdinstall/scripts/hostname new file mode 100755 index 0000000..a53fd80 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/hostname @@ -0,0 +1,48 @@ +#!/bin/sh +#- +# 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$ + +: ${DIALOG_OK=0} +: ${DIALOG_CANCEL=1} +: ${DIALOG_HELP=2} +: ${DIALOG_EXTRA=3} +: ${DIALOG_ITEM_HELP=4} +: ${DIALOG_ESC=255} + +exec 3>&1 +HOSTNAME=`dialog --backtitle 'FreeBSD Installer' --title 'Set Hostname' --nocancel --inputbox \ + 'Please choose a hostname for this machine. + +If you are running on a managed network, please ask your network administrator for an appropriate name.' \ + 0 0 $(hostname) 2>&1 1>&3` +if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +exec 3>&- + +echo "hostname=\"$HOSTNAME\"" > $BSDINSTALL_TMPETC/rc.conf.hostname +if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + hostname -s "$HOSTNAME" +fi diff --git a/usr.sbin/bsdinstall/scripts/jail b/usr.sbin/bsdinstall/scripts/jail new file mode 100755 index 0000000..d1adebb --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/jail @@ -0,0 +1,81 @@ +#!/bin/sh +#- +# 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$ + +echo "Begun Installation at $(date)" > $BSDINSTALL_LOG + +export BSDINSTALL_CHROOT=$1 +export DISTRIBUTIONS="`echo $DISTRIBUTIONS | sed 's/kernel\.[^ ]* //g'`" + +error() { + dialog --backtitle "FreeBSD Installer" --title "Abort" \ + --no-label "Exit" --yes-label "Restart" --yesno \ + "You have canceled an installation step. Would you like to restart the installation or exit the installer?" 0 0 + if [ $? -ne 0 ]; then + exit + else + test -f $PATH_FSTAB && bsdinstall umount + exec $0 + fi +} + + +rm -rf $BSDINSTALL_TMPETC +mkdir $BSDINSTALL_TMPETC + +trap error SIGINT # SIGINT is bad + +FETCH_DISTRIBUTIONS="" +for dist in $DISTRIBUTIONS; do + if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then + FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist" + fi +done + +if [ ! -z $FETCH_DISTRIBUTIONS ]; then + ALL_DISTRIBUTIONS=$DISTRIBUTIONS + DISTRIBUTIONS=$FETCH_DISTRIBUTIONS + bsdinstall distfetch || error + DISTRIBUTIONS=$ALL_DISTRIBUTIONS +fi + +bsdinstall distextract || error +bsdinstall rootpass || error + +trap true SIGINT # This section is optional +bsdinstall time +bsdinstall services + +dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \ + "Would you like to add users to the installed system now?" 0 0 && \ + bsdinstall adduser + +trap error SIGINT # SIGINT is bad again +bsdinstall config || error + +echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG + diff --git a/usr.sbin/bsdinstall/scripts/keymap b/usr.sbin/bsdinstall/scripts/keymap new file mode 100755 index 0000000..501b1d1 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/keymap @@ -0,0 +1,32 @@ +#!/bin/sh +#- +# 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$ + +kbdcontrol -d >/dev/null 2>&1 +if [ $? -eq 0 ]; then + kbdmap 3>&2 2>&1 1>&3 | grep 'keymap=' > $BSDINSTALL_TMPETC/rc.conf.keymap +fi diff --git a/usr.sbin/bsdinstall/scripts/mount b/usr.sbin/bsdinstall/scripts/mount new file mode 100755 index 0000000..fca8000 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/mount @@ -0,0 +1,55 @@ +#!/bin/sh +#- +# 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$ + +TMP_FSTAB=/tmp/bsdinstall-tmp-fstab + +cat $PATH_FSTAB | awk -v BSDINSTALL_CHROOT=$BSDINSTALL_CHROOT '{ + if ($2 ~ "^/.*") { + fsname = $2; + if (fsname == "/") + fsname = "" + printf("%s\t%s%s\t%s\t%s\t%s\t%s\n", $1, BSDINSTALL_CHROOT, + fsname, $3, $4, $5, $6); + } +}' > $TMP_FSTAB + +FILESYSTEMS=`cat $TMP_FSTAB | awk '/^[^#].*/ {if ($2 ~ "^/.*") printf("%s\n", $2);}' | sort -t /` + +for i in $FILESYSTEMS; do + mkdir -p $i 2>/dev/null + MNTERROR=`mount -F $TMP_FSTAB $i 2>&1` + if [ $? -ne 0 ]; then + dialog --backtitle "FreeBSD Installer" --title "Error" \ + --msgbox "Error mounting partition $i:\n$MNTERROR" 0 0 + exit 1 + fi +done + +# User might want a shell and require devfs, so mount it +mkdir $BSDINSTALL_CHROOT/dev 2>/dev/null +mount -t devfs devfs $BSDINSTALL_CHROOT/dev diff --git a/usr.sbin/bsdinstall/scripts/netconfig b/usr.sbin/bsdinstall/scripts/netconfig new file mode 100755 index 0000000..0374d12 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/netconfig @@ -0,0 +1,121 @@ +#!/bin/sh +#- +# 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$ + +INTERFACES="" +DIALOG_TAGS="" + +: ${DIALOG_OK=0} +: ${DIALOG_CANCEL=1} +: ${DIALOG_HELP=2} +: ${DIALOG_EXTRA=3} +: ${DIALOG_ITEM_HELP=4} +: ${DIALOG_ESC=255} + +echo -n > $BSDINSTALL_TMPETC/rc.conf.net + +for IF in `ifconfig -l`; do + test "$IF" = "lo0" && continue + (ifconfig -g wlan | egrep -wq $IF) && continue + INTERFACES="$INTERFACES $IF" + DESC=`sysctl -n dev.$(echo $IF | sed -E 's/([[:alpha:]]*)([[:digit:]]*)/\1.\2/g').%desc` + DIALOG_TAGS="$DIALOG_TAGS $IF \"$DESC\"" +done + +exec 3>&1 +INTERFACE=`echo $DIALOG_TAGS | xargs dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --menu 'Please select a network interface to configure:' 0 0 0 2>&1 1>&3` +if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +exec 3>&- + +# Do a dirty check to see if this a wireless interface -- there should be a +# better way +IFCONFIG_PREFIX="" +if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then + NEXT_WLAN_IFACE=wlan0 # XXX + echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/rc.conf.net + IFCONFIG_PREFIX="WPA " + if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + ifconfig $NEXT_WLAN_IFACE create wlandev $INTERFACE + ifconfig $NEXT_WLAN_IFACE up + fi + bsdinstall wlanconfig $NEXT_WLAN_IFACE || exec $0 + INTERFACE="$NEXT_WLAN_IFACE" +fi + +dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0 +if [ $? -eq $DIALOG_OK ]; then + echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/rc.conf.net + + if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0 + dhclient $INTERFACE 2>> $BSDINSTALL_LOG + if [ $? -ne 0 ]; then + dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0 + exec $0 + fi + fi + exit 0 +fi + +IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'` +NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'` +ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'` + +exec 3>&1 +IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \ + 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \ + 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \ + 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \ + \ + 'Nameserver' 5 0 "" 5 20 16 0 \ + 'Search Domain' 6 0 "" 6 20 20 0 \ +2>&1 1>&3) +if [ $? -eq $DIALOG_CANCEL ]; then exec $0; fi +exec 3>&- + +echo $INTERFACE $IF_CONFIG | + awk -v prefix="$IFCONFIG_PREFIX" '{ + printf("ifconfig_%s=\"%s%s netmask %s\"\n", $1, prefix, $2, $3); + printf("defaultrouter=\"%s\"\n", $4); + }' >> $BSDINSTALL_TMPETC/rc.conf.net + +if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + . $BSDINSTALL_TMPETC/rc.conf.net + ifconfig $INTERFACE `eval echo \\\$ifconfig_$INTERFACE` + route delete default + route add default $defaultrouter +fi + + +echo $IF_CONFIG | + awk '{ + if ($4 != "") + printf("nameserver %s\n", $4); + if ($5 != "") + printf("search %s\n", $5); + }' > $BSDINSTALL_TMPETC/resolv.conf + diff --git a/usr.sbin/bsdinstall/scripts/rootpass b/usr.sbin/bsdinstall/scripts/rootpass new file mode 100755 index 0000000..b7177fc --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/rootpass @@ -0,0 +1,37 @@ +#!/bin/sh +#- +# 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$ + +clear +echo "FreeBSD Installer" +echo "========================" +echo + +echo "Please select a password for the system management account (root):" + +chroot $BSDINSTALL_CHROOT passwd root + diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services new file mode 100755 index 0000000..01c25fe --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/services @@ -0,0 +1,53 @@ +#!/bin/sh +#- +# 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$ + +if [ -f $BSDINSTALL_TMPETC/rc.conf.services ]; then + eval `sed -e s/YES/on/I -e s/NO/off/I $BSDINSTALL_TMPETC/rc.conf.services` +else + # Default service states. Everything is off if not enabled. + sshd_enable="on" +fi + +echo -n > $BSDINSTALL_TMPETC/rc.conf.services + +exec 3>&1 +DAEMONS=$(dialog --backtitle "FreeBSD Installer" \ + --title "System Configuration" --nocancel --separate-output \ + --checklist "Choose the services you would like to be started at boot:" \ + 0 0 0 \ + sshd "Secure shell daemon" ${sshd_enable:-off} \ + moused "PS/2 mouse pointer on console" ${moused_enable:-off} \ + ntpd "Synchronize system and network time" ${ntpd_enable:-off} \ + powerd "Adjust CPU frequency dynamically" ${powerd_enable:-off} \ +2>&1 1>&3) +exec 3>&- + +for daemon in $DAEMONS; do + echo ${daemon}_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services +done + diff --git a/usr.sbin/bsdinstall/scripts/time b/usr.sbin/bsdinstall/scripts/time new file mode 100755 index 0000000..74400b6 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/time @@ -0,0 +1,29 @@ +#!/bin/sh +#- +# 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$ + +chroot $BSDINSTALL_CHROOT tzsetup diff --git a/usr.sbin/bsdinstall/scripts/umount b/usr.sbin/bsdinstall/scripts/umount new file mode 100755 index 0000000..c19f6f3 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/umount @@ -0,0 +1,42 @@ +#!/bin/sh +#- +# 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$ + +TMP_FSTAB=/tmp/bsdinstall-tmp-fstab + +cat $PATH_FSTAB | awk -v BSDINSTALL_CHROOT=$BSDINSTALL_CHROOT '{ + if ($2 ~ "^/.*") { + fsname = $2; + if (fsname == "/") + fsname = "" + printf("%s\t%s%s\t%s\t%s\t%s\t%s\n", $1, BSDINSTALL_CHROOT, + fsname, $3, $4, $5, $6); + } +}' > $TMP_FSTAB + +umount $BSDINSTALL_CHROOT/dev 2>/dev/null +umount -F $TMP_FSTAB -a 2>/dev/null diff --git a/usr.sbin/bsdinstall/scripts/wlanconfig b/usr.sbin/bsdinstall/scripts/wlanconfig new file mode 100755 index 0000000..d95ccff --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/wlanconfig @@ -0,0 +1,137 @@ +#!/bin/sh +#- +# 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$ + +echo -n > $BSDINSTALL_TMPETC/wpa_supplicant.conf +chmod 0600 $BSDINSTALL_TMPETC/wpa_supplicant.conf + +echo "ctrl_interface=/var/run/wpa_supplicant" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +echo "eapol_version=2" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +echo "ap_scan=1" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +echo "fast_reauth=1" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +echo >> $BSDINSTALL_TMPETC/wpa_supplicant.conf + +# Try to reach wpa_supplicant. If it isn't running and we can modify the +# existing system, start it. Otherwise, fail. +(wpa_cli ping >/dev/null 2>/dev/null || ([ ! -z $BSDINSTALL_CONFIGCURRENT ] && \ + wpa_supplicant -B -i $1 -c $BSDINSTALL_TMPETC/wpa_supplicant.conf)) || \ + (dialog --backtitle "FreeBSD Installer" --title "Error" --msgbox \ + "Could not start wpa_supplicant!" 0 0; exit 1) || exit 1 + +# See if we succeeded +wpa_cli ping >/dev/null 2>/dev/null +if [ $? -ne 0 -a -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle "FreeBSD Installer" --title "Error" --msgbox \ + "Wireless cannot be configured without making changes to the local system!" \ 0 0 + exit 1 +fi + +wpa_cli scan >>$BSDINSTALL_LOG +dialog --backtitle "FreeBSD Installer" --title "Scanning" --ok-label "Skip" \ + --pause "Waiting 5 seconds to scan for wireless networks..." \ + 9 40 5 || exit 1 + +SCAN_RESULTS=`wpa_cli scan_results` +NETWORKS=`echo "$SCAN_RESULTS" | awk -F '\t' \ + '/..:..:..:..:..:../ {if (length($5) > 0) printf("\"%s\"\t%s\n", $5, $4);}' | + sort | uniq` + +if [ -z $SCAN_RESULTS ]; then + dialog --backtitle "FreeBSD Installer" --title "Error" \ + --yesno "No wireless networks were found. Rescan?" 0 0 && \ + exec $0 $@ + exit 1 +fi + +exec 3>&1 +NETWORK=`sh -c "dialog --extra-button --extra-label \"Rescan\" \ + --backtitle \"FreeBSD Installer\" --title \"Network Selection\" --menu \ + \"Select a wireless network to connect to.\" 0 0 0 \ + $(echo $NETWORKS | tr '\n' ' ')" 2>&1 1>&3` +case $? in +0) # OK + ;; +1) # Cancel + exit 1 + ;; +3) # Rescan + exec $0 $@ + ;; +esac +exec 3>&- + +ENCRYPTION=`echo "$NETWORKS" | awk -F '\t' \ + "/^\"$NETWORK\"\t/ {printf(\"%s\n\", \\\$2 );}"` + +if echo $ENCRYPTION | grep -q 'PSK'; then + exec 3>&1 + PASS=`dialog --insecure --backtitle "FreeBSD Installer" \ + --title "WPA Setup" --mixedform "" 0 0 0 \ + "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \ + "Password" 2 0 "" 2 12 15 0 1 \ + 2>&1 1>&3` \ + || exec $0 $@ + exec 3>&- +echo "network={ + ssid=\"$NETWORK\" + psk=\"$PASS\" + priority=5 +}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +elif echo $ENCRYPTION | grep -q WEP; then + echo FOO + exec 3>&1 + WEPKEY=`dialog --insecure --backtitle "FreeBSD Installer" \ + --title "WEP Setup" --mixedform "" 0 0 0 \ + "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \ + "WEP Key 0" 2 0 "" 2 12 15 0 1 \ + 2>&1 1>&3` \ + || exec $0 $@ +echo "network={ + ssid=\"$NETWORK\" + key_mgmt=NONE + wep_key0=\"$WEPKEY\" + wep_tx_keyidx=0 + priority=5 +}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +else # Open +echo "network={ + ssid=\"$NETWORK\" + key_mgmt=NONE + priority=5 +}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf +fi + +# Connect to any open networks policy +echo "network={ + priority=5 + key_mgmt=NONE +}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf + +# Bring up new network +test ! -z $BSDINSTALL_CONFIGCURRENT && wpa_cli reconfigure >>$BSDINSTALL_LOG + +exit 0 |