diff --git a/usr.sbin/bsdinstall/Makefile b/usr.sbin/bsdinstall/Makefile index 88cb691d8dda..761051a5f48f 100644 --- a/usr.sbin/bsdinstall/Makefile +++ b/usr.sbin/bsdinstall/Makefile @@ -1,9 +1,18 @@ # $FreeBSD$ +OSNAME?= FreeBSD SUBDIR= distextract distfetch partedit scripts SUBDIR_PARALLEL= SCRIPTS= bsdinstall MAN= bsdinstall.8 PACKAGE= bsdinstall +GENHDRS= opt_osname.h +SRCS+= ${GENHDRS} +CLEANFILES+= ${GENHDRS} + +opt_osname.h: .PHONY + if ! grep -q "^#define OSNAME \"${OSNAME}\"$"" ${.TARGET}; then \ + echo "#define OSNAME \"${OSNAME}\"" > ${.TARGET}; \ + fi .include diff --git a/usr.sbin/bsdinstall/distextract/Makefile b/usr.sbin/bsdinstall/distextract/Makefile index 5e9f2b9e1473..6ae9bb65e8fb 100644 --- a/usr.sbin/bsdinstall/distextract/Makefile +++ b/usr.sbin/bsdinstall/distextract/Makefile @@ -1,10 +1,10 @@ # $FreeBSD$ BINDIR= ${LIBEXECDIR}/bsdinstall PROG= distextract -CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib +CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib -I${.OBJDIR}/.. LIBADD= archive bsddialog m MAN= .include diff --git a/usr.sbin/bsdinstall/distextract/distextract.c b/usr.sbin/bsdinstall/distextract/distextract.c index f7f973fe336c..30400ba0f021 100644 --- a/usr.sbin/bsdinstall/distextract/distextract.c +++ b/usr.sbin/bsdinstall/distextract/distextract.c @@ -1,332 +1,334 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Nathan Whitehorn * Copyright (c) 2014 Devin Teske * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "opt_osname.h" + /* Data to process */ static const char *distdir = NULL; static struct archive *archive = NULL; /* Function prototypes */ static void sig_int(int sig); static int count_files(const char *file); static int extract_files(struct bsddialog_fileminibar *file); #define _errx(...) (bsddialog_end(), errx(__VA_ARGS__)) int main(void) { char *chrootdir; char *distributions; char *distribs, *distrib; int retval; size_t minibar_size = sizeof(struct bsddialog_fileminibar); unsigned int nminibars; struct bsddialog_fileminibar *dists; struct bsddialog_progviewconf pvconf; struct bsddialog_conf conf; struct sigaction act; char error[PATH_MAX + 512]; if ((distributions = getenv("DISTRIBUTIONS")) == NULL) errx(EXIT_FAILURE, "DISTRIBUTIONS variable is not set"); if ((distdir = getenv("BSDINSTALL_DISTDIR")) == NULL) distdir = ""; if ((distribs = strdup(distributions)) == NULL) errx(EXIT_FAILURE, "memory error"); if (bsddialog_init() == BSDDIALOG_ERROR) errx(EXIT_FAILURE, "Error libbsdialog: %s", bsddialog_geterror()); bsddialog_initconf(&conf); - bsddialog_backtitle(&conf, "FreeBSD Installer"); + bsddialog_backtitle(&conf, OSNAME " Installer"); bsddialog_infobox(&conf, "Checking distribution archives.\nPlease wait...", 4, 35); /* Parse $DISTRIBUTIONS */ nminibars = 0; dists = NULL; while ((distrib = strsep(&distribs, "\t\n\v\f\r ")) != NULL) { if (strlen(distrib) == 0) continue; /* Allocate a new struct for the distribution */ dists = realloc(dists, (nminibars + 1) * minibar_size); if (dists == NULL) _errx(EXIT_FAILURE, "Out of memory!"); /* Set file path */ dists[nminibars].path = distrib; /* Set mini bar label */ dists[nminibars].label = strrchr(dists[nminibars].path, '/'); if (dists[nminibars].label == NULL) dists[nminibars].label = dists[nminibars].path; /* Set initial length in files (-1 == error) */ dists[nminibars].size = count_files(dists[nminibars].path); if (dists[nminibars].size < 0) { bsddialog_end(); return (EXIT_FAILURE); } /* Set initial status and implicitly miniperc to pending */ dists[nminibars].status = BSDDIALOG_MG_PENDING; /* Set initial read */ dists[nminibars].read = 0; nminibars += 1; } /* Optionally chdir(2) into $BSDINSTALL_CHROOT */ chrootdir = getenv("BSDINSTALL_CHROOT"); if (chrootdir != NULL && chdir(chrootdir) != 0) { snprintf(error, sizeof(error), "Could not change to directory %s: %s\n", chrootdir, strerror(errno)); conf.title = "Error"; bsddialog_msgbox(&conf, error, 0, 0); bsddialog_end(); return (EXIT_FAILURE); } /* Set cleanup routine for Ctrl-C action */ act.sa_handler = sig_int; sigaction(SIGINT, &act, 0); conf.title = "Archive Extraction"; conf.auto_minwidth = 40; pvconf.callback = extract_files; pvconf.refresh = 1; pvconf.fmtbottomstr = "%10lli files read @ %'9.1f files/sec."; bsddialog_total_progview = 0; bsddialog_interruptprogview = bsddialog_abortprogview = false; retval = bsddialog_progressview(&conf, "\nExtracting distribution files...\n", 0, 0, &pvconf, nminibars, dists); if (retval == BSDDIALOG_ERROR) { fprintf(stderr, "progressview error: %s\n", bsddialog_geterror()); } bsddialog_end(); free(distribs); free(dists); return (retval); } static void sig_int(int sig __unused) { bsddialog_interruptprogview = true; } /* * Returns number of files in archive file. Parses $BSDINSTALL_DISTDIR/MANIFEST * if it exists, otherwise uses archive(3) to read the archive file. */ static int count_files(const char *file) { static FILE *manifest = NULL; char *p; int file_count; int retval; size_t span; struct archive_entry *entry; char line[512]; char path[PATH_MAX]; char errormsg[PATH_MAX + 512]; struct bsddialog_conf conf; if (manifest == NULL) { snprintf(path, sizeof(path), "%s/MANIFEST", distdir); manifest = fopen(path, "r"); } if (manifest != NULL) { rewind(manifest); while (fgets(line, sizeof(line), manifest) != NULL) { p = &line[0]; span = strcspn(p, "\t") ; if (span < 1 || strncmp(p, file, span) != 0) continue; /* * We're at the right manifest line. The file count is * in the third element */ span = strcspn(p += span + (*p != '\0' ? 1 : 0), "\t"); span = strcspn(p += span + (*p != '\0' ? 1 : 0), "\t"); if (span > 0) { file_count = (int)strtol(p, (char **)NULL, 10); if (file_count == 0 && errno == EINVAL) continue; return (file_count); } } } /* * Either no manifest, or manifest didn't mention this archive. * Use archive(3) to read the archive, counting files within. */ bsddialog_initconf(&conf); if ((archive = archive_read_new()) == NULL) { snprintf(errormsg, sizeof(errormsg), "Error: %s\n", archive_error_string(NULL)); conf.title = "Extract Error"; bsddialog_msgbox(&conf, errormsg, 0, 0); return (-1); } archive_read_support_format_all(archive); archive_read_support_filter_all(archive); snprintf(path, sizeof(path), "%s/%s", distdir, file); retval = archive_read_open_filename(archive, path, 4096); if (retval != ARCHIVE_OK) { snprintf(errormsg, sizeof(errormsg), "Error while extracting %s: %s\n", file, archive_error_string(archive)); conf.title = "Extract Error"; bsddialog_msgbox(&conf, errormsg, 0, 0); archive = NULL; return (-1); } file_count = 0; while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) file_count++; archive_read_free(archive); archive = NULL; return (file_count); } static int extract_files(struct bsddialog_fileminibar *file) { int retval; struct archive_entry *entry; char path[PATH_MAX]; char errormsg[PATH_MAX + 512]; struct bsddialog_conf conf; bsddialog_initconf(&conf); /* Open the archive if necessary */ if (archive == NULL) { if ((archive = archive_read_new()) == NULL) { snprintf(errormsg, sizeof(errormsg), "Error: %s\n", archive_error_string(NULL)); conf.title = "Extract Error"; bsddialog_msgbox(&conf, errormsg, 0, 0); bsddialog_abortprogview = true; return (-1); } archive_read_support_format_all(archive); archive_read_support_filter_all(archive); snprintf(path, sizeof(path), "%s/%s", distdir, file->path); retval = archive_read_open_filename(archive, path, 4096); if (retval != 0) { snprintf(errormsg, sizeof(errormsg), "Error opening %s: %s\n", file->label, archive_error_string(archive)); conf.title = "Extract Error"; bsddialog_msgbox(&conf, errormsg, 0, 0); file->status = BSDDIALOG_MG_FAILED; bsddialog_abortprogview = true; return (-1); } } /* Read the next archive header */ retval = archive_read_next_header(archive, &entry); /* If that went well, perform the extraction */ if (retval == ARCHIVE_OK) retval = archive_read_extract(archive, entry, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); /* Test for either EOF or error */ if (retval == ARCHIVE_EOF) { archive_read_free(archive); archive = NULL; file->status = BSDDIALOG_MG_DONE; /*Done*/; return (100); } else if (retval != ARCHIVE_OK && !(retval == ARCHIVE_WARN && strcmp(archive_error_string(archive), "Can't restore time") == 0)) { /* * Print any warning/error messages except inability to set * ctime/mtime, which is not fatal, or even interesting, * for our purposes. Would be nice if this were a libarchive * option. */ snprintf(errormsg, sizeof(errormsg), "Error while extracting %s: %s\n", file->label, archive_error_string(archive)); conf.title = "Extract Error"; bsddialog_msgbox(&conf, errormsg, 0, 0); file->status = BSDDIALOG_MG_FAILED; /* Failed */ bsddialog_abortprogview = true; return (-1); } bsddialog_total_progview++; file->read++; /* Calculate [overall] percentage of completion (if possible) */ if (file->size >= 0) return (file->read * 100 / file->size); else return (-1); } diff --git a/usr.sbin/bsdinstall/distfetch/Makefile b/usr.sbin/bsdinstall/distfetch/Makefile index f4ae37edf1a5..0104df0e3aec 100644 --- a/usr.sbin/bsdinstall/distfetch/Makefile +++ b/usr.sbin/bsdinstall/distfetch/Makefile @@ -1,10 +1,10 @@ # $FreeBSD$ BINDIR= ${LIBEXECDIR}/bsdinstall PROG= distfetch -CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib +CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib -I${.OBJDIR}/.. LIBADD= fetch bsddialog MAN= .include diff --git a/usr.sbin/bsdinstall/distfetch/distfetch.c b/usr.sbin/bsdinstall/distfetch/distfetch.c index c5749c07854a..6963ee08968f 100644 --- a/usr.sbin/bsdinstall/distfetch/distfetch.c +++ b/usr.sbin/bsdinstall/distfetch/distfetch.c @@ -1,256 +1,258 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Nathan Whitehorn * Copyright (c) 2014 Devin Teske * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include +#include "opt_osname.h" + static int fetch_files(int nfiles, char **urls); int main(void) { char *diststring; char **urls; int i; int ndists = 0; int nfetched; char error[PATH_MAX + 512]; struct bsddialog_conf conf; if (getenv("DISTRIBUTIONS") == NULL) errx(EXIT_FAILURE, "DISTRIBUTIONS variable is not set"); diststring = strdup(getenv("DISTRIBUTIONS")); 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 *)); if (urls == NULL) { free(diststring); errx(EXIT_FAILURE, "Error: distfetch URLs out of memory!"); } if (bsddialog_init() == BSDDIALOG_ERROR) { free(diststring); errx(EXIT_FAILURE, "Error libbsddialog: %s\n", bsddialog_geterror()); } bsddialog_initconf(&conf); - bsddialog_backtitle(&conf, "FreeBSD Installer"); + bsddialog_backtitle(&conf, OSNAME " Installer"); for (i = 0; i < ndists; i++) { urls[i] = malloc(PATH_MAX); snprintf(urls[i], PATH_MAX, "%s/%s", getenv("BSDINSTALL_DISTSITE"), strsep(&diststring, " \t")); } if (chdir(getenv("BSDINSTALL_DISTDIR")) != 0) { snprintf(error, sizeof(error), "Could not change to directory %s: %s\n", getenv("BSDINSTALL_DISTDIR"), strerror(errno)); conf.title = "Error"; bsddialog_msgbox(&conf, error, 0, 0); bsddialog_end(); return (EXIT_FAILURE); } nfetched = fetch_files(ndists, urls); bsddialog_end(); free(diststring); for (i = 0; i < ndists; i++) free(urls[i]); free(urls); return ((nfetched == ndists) ? EXIT_SUCCESS : EXIT_FAILURE); } static int fetch_files(int nfiles, char **urls) { FILE *fetch_out; FILE *file_out; const char **minilabel; int *miniperc; int perc; int i; int last_progress; int nsuccess = 0; /* Number of files successfully downloaded */ int progress = 0; size_t chunk; off_t current_bytes; off_t fsize; off_t total_bytes; float file_perc; float mainperc_file; struct url_stat ustat; char errormsg[PATH_MAX + 512]; uint8_t block[4096]; struct bsddialog_conf errconf; struct bsddialog_conf mgconf; /* Make the transfer list for mixedgauge */ minilabel = calloc(sizeof(char *), nfiles); miniperc = calloc(sizeof(int), nfiles); if (minilabel == NULL || miniperc == NULL) errx(EXIT_FAILURE, "Error: distfetch minibars out of memory!"); for (i = 0; i < nfiles; i++) { minilabel[i] = strrchr(urls[i], '/'); if (minilabel[i] != NULL) minilabel[i]++; else minilabel[i] = urls[i]; miniperc[i] = BSDDIALOG_MG_PENDING; } bsddialog_initconf(&errconf); bsddialog_infobox(&errconf, "Connecting to server.\nPlease wait...", 0, 0); /* 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; } else { total_bytes = 0; break; } } errconf.title = "Fetch Error"; errconf.clear = true; bsddialog_initconf(&mgconf); mgconf.title = "Fetching Distribution"; mgconf.auto_minwidth = 40; mainperc_file = 100.0 / nfiles; current_bytes = 0; for (i = 0; i < nfiles; i++) { fetchLastErrCode = 0; fetch_out = fetchXGetURL(urls[i], &ustat, ""); if (fetch_out == NULL) { snprintf(errormsg, sizeof(errormsg), "Error (URL) while fetching %s: %s\n", urls[i], fetchLastErrString); miniperc[2] = BSDDIALOG_MG_FAILED; bsddialog_msgbox(&errconf, errormsg, 0, 0); total_bytes = 0; continue; } miniperc[i] = BSDDIALOG_MG_INPROGRESS; fsize = 0; file_out = fopen(minilabel[i], "w+"); if (file_out == NULL) { snprintf(errormsg, sizeof(errormsg), "Error (fopen) while fetching %s: %s\n", urls[i], strerror(errno)); miniperc[i] = BSDDIALOG_MG_FAILED; bsddialog_msgbox(&errconf, errormsg, 0, 0); fclose(fetch_out); total_bytes = 0; 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; last_progress = progress; if (total_bytes > 0) { progress = (current_bytes * 100) / total_bytes; } else { file_perc = ustat.size > 0 ? (fsize * 100) / ustat.size : 0; progress = (i * mainperc_file) + ((file_perc * mainperc_file) / 100); } if (ustat.size > 0) { perc = (fsize * 100) / ustat.size; miniperc[i] = perc; } if (progress > last_progress) { bsddialog_mixedgauge(&mgconf, "\nFetching distribution files...\n", 0, 0, progress, nfiles, minilabel, miniperc); } } if (ustat.size > 0 && fsize < ustat.size) { if (fetchLastErrCode == 0) snprintf(errormsg, sizeof(errormsg), "Error (undone) while fetching %s: %s\n", urls[i], strerror(errno)); else snprintf(errormsg, sizeof(errormsg), "Error (libfetch) while fetching %s: %s\n", urls[i], fetchLastErrString); miniperc[i] = BSDDIALOG_MG_FAILED; bsddialog_msgbox(&errconf, errormsg, 0, 0); total_bytes = 0; } else { miniperc[i] = BSDDIALOG_MG_DONE; nsuccess++; } fclose(fetch_out); fclose(file_out); } bsddialog_mixedgauge(&mgconf, "\nFetching distribution completed\n", 0, 0, progress, nfiles, minilabel, miniperc); free(minilabel); free(miniperc); return (nsuccess); } diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile index f89a1d374fb8..96c4ddb53961 100644 --- a/usr.sbin/bsdinstall/partedit/Makefile +++ b/usr.sbin/bsdinstall/partedit/Makefile @@ -1,27 +1,27 @@ # $FreeBSD$ BINDIR= ${LIBEXECDIR}/bsdinstall PROG= partedit LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \ ${BINDIR}/partedit ${BINDIR}/scriptedpart SYMLINKS= ../libexec/bsdinstall/partedit /usr/sbin/sade -CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib +CFLAGS+= -I${SRCTOP}/contrib/bsddialog/lib -I${.OBJDIR}/.. LIBADD+= geom util bsddialog PARTEDIT_ARCH= ${MACHINE} .if ${MACHINE} == "i386" || ${MACHINE} == "amd64" PARTEDIT_ARCH= x86 .elif ${MACHINE} == "arm64" || ${MACHINE} == "riscv" PARTEDIT_ARCH= efi .endif .if !exists(partedit_${PARTEDIT_ARCH}.c) PARTEDIT_ARCH= generic .endif SRCS= diskmenu.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \ part_wizard.c scripted.c WARNS?= 3 MAN= sade.8 .include diff --git a/usr.sbin/bsdinstall/partedit/part_wizard.c b/usr.sbin/bsdinstall/partedit/part_wizard.c index a030608ac764..83fc29eb0359 100644 --- a/usr.sbin/bsdinstall/partedit/part_wizard.c +++ b/usr.sbin/bsdinstall/partedit/part_wizard.c @@ -1,395 +1,395 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #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 *wizard_partition(struct gmesh *mesh, const char *disk); int part_wizard(const char *fsreq) { char *disk, *schemeroot; const char *fstype; struct gmesh mesh; int error; struct bsddialog_conf conf; bsddialog_initconf(&conf); if (fsreq != NULL) fstype = fsreq; else fstype = "ufs"; startwizard: error = geom_gettree(&mesh); bsddialog_backtitle(&conf, "FreeBSD Installer"); error = geom_gettree(&mesh); disk = boot_disk_select(&mesh); if (disk == NULL) return (1); bsddialog_clearterminal(); bsddialog_backtitle(&conf, "FreeBSD Installer"); schemeroot = wizard_partition(&mesh, disk); free(disk); if (schemeroot == NULL) return (1); geom_deletetree(&mesh); bsddialog_clearterminal(); bsddialog_backtitle(&conf, "FreeBSD Installer"); error = geom_gettree(&mesh); error = wizard_makeparts(&mesh, schemeroot, fstype, 1); if (error) goto startwizard; free(schemeroot); geom_deletetree(&mesh); return (0); } char * boot_disk_select(struct gmesh *mesh) { struct gclass *classp; struct gconfig *gc; struct ggeom *gp; struct gprovider *pp; struct bsddialog_menuitem *disks = NULL; const char *type, *desc; char diskdesc[512]; char *chosen; int i, button, fd, selected, n = 0; struct bsddialog_conf conf; bsddialog_initconf(&conf); LIST_FOREACH(classp, &mesh->lg_class, lg_class) { if (strcmp(classp->lg_name, "DISK") != 0 && strcmp(classp->lg_name, "RAID") != 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) { desc = type = NULL; LIST_FOREACH(gc, &pp->lg_config, lg_config) { if (strcmp(gc->lg_name, "type") == 0) type = gc->lg_val; if (strcmp(gc->lg_name, "descr") == 0) desc = gc->lg_val; } /* Skip swap-backed md and WORM devices */ if (strcmp(classp->lg_name, "MD") == 0 && type != NULL && strcmp(type, "swap") == 0) continue; if (strncmp(pp->lg_name, "cd", 2) == 0) continue; /* * Check if the disk is available to be opened for * write operations, it helps prevent the USB * stick used to boot from being listed as an option */ fd = g_open(pp->lg_name, 1); if (fd == -1) { continue; } g_close(fd); 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, "md", 2) == 0) strcat(diskdesc, " Memory Disk"); else strcat(diskdesc, " Disk"); if (desc != NULL) snprintf(diskdesc, sizeof(diskdesc), "%s <%s>", diskdesc, desc); disks[n-1].prefix = ""; disks[n-1].on = false; disks[n-1].depth = 0; disks[n-1].desc = strdup(diskdesc); disks[n-1].bottomdesc = ""; } } } if (n > 1) { conf.title = "Partitioning"; button = bsddialog_menu(&conf, - "Select the disk on which to install FreeBSD.", 0, 0, 0, + "Select the disk on which to install " OSNAME ".", 0, 0, 0, n, disks, &selected); chosen = (button == BSDDIALOG_OK) ? strdup(disks[selected].name) : NULL; } else if (n == 1) { chosen = strdup(disks[0].name); } else { chosen = NULL; } for (i = 0; i < n; i++) free((char*)disks[i].desc); 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) { 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 *retval = NULL; const char *scheme = NULL; char message[512]; int choice; struct bsddialog_conf conf; bsddialog_initconf(&conf); LIST_FOREACH(classp, &mesh->lg_class, lg_class) if (strcmp(classp->lg_name, "PART") == 0) 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; } } } /* Treat uncommitted scheme deletions as no scheme */ if (scheme != NULL && strcmp(scheme, "(none)") == 0) scheme = NULL; query: conf.button.ok_label = "Entire Disk"; conf.button.cancel_label = "Partition"; if (gpart != NULL) conf.button.default_cancel = true; snprintf(message, sizeof(message), "Would you like to use this entire " - "disk (%s) for FreeBSD or partition it to share it with other " + "disk (%s) for " OSNAME " or partition it to share it with other " "operating systems? Using the entire disk will erase any data " "currently stored there.", disk); conf.title = "Partition"; choice = bsddialog_yesno(&conf, message, 9, 45); conf.button.ok_label = NULL; conf.button.cancel_label = NULL; conf.button.default_cancel = false; if (choice == BSDDIALOG_NO && 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 " + OSNAME ", it must be repartitioned. This will destroy all " "data on the disk. Are you sure you want to proceed?", scheme); conf.title = "Non-bootable Disk"; subchoice = bsddialog_yesno(&conf, warning, 0, 0); if (subchoice != BSDDIALOG_YES) goto query; gpart_destroy(gpart); scheme = choose_part_type(default_scheme()); if (scheme == NULL) return NULL; gpart_partition(disk, scheme); } if (scheme == NULL || choice == 0) { if (gpart != NULL && scheme != NULL) { /* Erase partitioned disk */ conf.title = "Confirmation"; choice = bsddialog_yesno(&conf, "This will erase " "the disk. Are you sure you want to proceed?", 0, 0); if (choice != BSDDIALOG_YES) goto query; gpart_destroy(gpart); } scheme = choose_part_type(default_scheme()); if (scheme == NULL) return NULL; gpart_partition(disk, scheme); } if (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); } int wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype, int interactive) { struct gclass *classp; struct ggeom *gp; struct gprovider *pp; char *fsnames[] = {"freebsd-ufs", "freebsd-zfs"}; char *fsname; struct gmesh submesh; char swapsizestr[10], rootsizestr[10]; intmax_t swapsize, available; int retval; struct bsddialog_conf conf; if (strcmp(fstype, "zfs") == 0) { fsname = fsnames[1]; } else { /* default to UFS */ fsname = fsnames[0]; } 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; pp = provider_for_name(mesh, disk); available = gpart_max_free(gp, NULL)*pp->lg_sectorsize; if (interactive && 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 " + "install " OSNAME " (%s free, %s required). Would you like " "to choose another disk or to open the partition editor?", disk, availablestr, neededstr); bsddialog_initconf(&conf); conf.button.ok_label = "Another Disk"; conf.button.cancel_label = "Editor"; conf.title = "Warning"; retval = bsddialog_yesno(&conf, message, 0, 0); return (!retval); /* Editor -> return 0 */ } 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, fsname, 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 index bcf107f7b397..22d1dbfca194 100644 --- a/usr.sbin/bsdinstall/partedit/partedit.c +++ b/usr.sbin/bsdinstall/partedit/partedit.c @@ -1,625 +1,625 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "diskmenu.h" #include "partedit.h" struct pmetadata_head part_metadata; static int sade_mode = 0; static int apply_changes(struct gmesh *mesh); static void apply_workaround(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); static void sigint_handler(int sig) { struct gmesh mesh; /* Revert all changes and exit dialog-mode cleanly on SIGINT */ geom_gettree(&mesh); gpart_revert_all(&mesh); geom_deletetree(&mesh); bsddialog_end(); exit(1); } int main(int argc, const char **argv) { struct partition_metadata *md; const char *progname, *prompt; struct partedit_item *items = NULL; struct gmesh mesh; int i, op, nitems; int error; struct bsddialog_conf conf; progname = getprogname(); if (strcmp(progname, "sade") == 0) sade_mode = 1; TAILQ_INIT(&part_metadata); init_fstab_metadata(); if (bsddialog_init() == BSDDIALOG_ERROR) err(1, "%s", bsddialog_geterror()); bsddialog_initconf(&conf); if (!sade_mode) - bsddialog_backtitle(&conf, "FreeBSD Installer"); + bsddialog_backtitle(&conf, OSNAME " Installer"); i = 0; /* Revert changes on SIGINT */ signal(SIGINT, sigint_handler); if (strcmp(progname, "autopart") == 0) { /* Guided */ prompt = "Please review the disk setup. When complete, press " "the Finish button."; /* Experimental ZFS autopartition support */ if (argc > 1 && strcmp(argv[1], "zfs") == 0) { part_wizard("zfs"); } else { part_wizard("ufs"); } } else if (strcmp(progname, "scriptedpart") == 0) { error = scripted_editor(argc, argv); prompt = NULL; if (error != 0) { bsddialog_end(); return (error); } } else { - prompt = "Create partitions for FreeBSD, F1 for help.\n" + prompt = "Create partitions for " OSNAME ", F1 for help.\n" "No changes will be made until you select Finish."; } /* Show the part editor either immediately, or to confirm wizard */ while (prompt != NULL) { bsddialog_clearterminal(); if (!sade_mode) bsddialog_backtitle(&conf, "FreeBSD Installer"); error = geom_gettree(&mesh); if (error == 0) items = read_geom_mesh(&mesh, &nitems); if (error || items == NULL) { conf.title = "Error"; bsddialog_msgbox(&conf, "No disks found. If you need " "to install a kernel driver, choose Shell at the " "installation menu.", 0, 0); break; } get_mount_points(items, nitems); if (i >= nitems) i = nitems - 1; op = diskmenu_show("Partition Editor", prompt, items, nitems, &i); switch (op) { case BUTTON_CREATE: gpart_create((struct gprovider *)(items[i].cookie), NULL, NULL, NULL, NULL, 1); break; case BUTTON_DELETE: gpart_delete((struct gprovider *)(items[i].cookie)); break; case BUTTON_MODIFY: gpart_edit((struct gprovider *)(items[i].cookie)); break; case BUTTON_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 BUTTON_AUTO: part_wizard("ufs"); break; } error = 0; if (op == BUTTON_FINISH) { conf.button.ok_label = "Commit"; conf.button.with_extra = true; conf.button.extra_label = "Revert & Exit"; conf.button.cancel_label = "Back"; conf.title = "Confirmation"; op = bsddialog_yesno(&conf, "Your changes will now be " "written to disk. If you have chosen to overwrite " "existing data, it will be PERMANENTLY ERASED. Are " "you sure you want to commit your changes?", 0, 0); conf.button.ok_label = NULL; conf.button.with_extra = false; conf.button.extra_label = NULL; conf.button.cancel_label = NULL; if (op == BSDDIALOG_OK && validate_setup()) { /* Save */ error = apply_changes(&mesh); if (!error) apply_workaround(&mesh); break; } else if (op == BSDDIALOG_EXTRA) { /* Quit */ gpart_revert_all(&mesh); error = -1; break; } } geom_deletetree(&mesh); free(items); } if (prompt == NULL) { error = geom_gettree(&mesh); if (validate_setup()) { error = apply_changes(&mesh); } else { gpart_revert_all(&mesh); error = -1; } } geom_deletetree(&mesh); free(items); bsddialog_end(); 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, *root = NULL; int button; struct bsddialog_conf conf; TAILQ_FOREACH(md, &part_metadata, metadata) { if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) root = md; /* XXX: Check for duplicate mountpoints */ } bsddialog_initconf(&conf); if (root == NULL) { conf.title = "Error"; bsddialog_msgbox(&conf, "No root partition was found. " - "The root FreeBSD partition must have a mountpoint " + "The root " OSNAME " partition must have a mountpoint " "of '/'.", 0, 0); return (false); } /* * Check for root partitions that we aren't formatting, which is * usually a mistake */ if (root->newfs == NULL && !sade_mode) { conf.button.default_cancel = true; conf.title = "Warning"; button = bsddialog_yesno(&conf, "The chosen root partition " "has a preexisting filesystem. If it contains an existing " - "FreeBSD system, please update it with freebsd-update " + OSNAME " system, please update it with freebsd-update " "instead of installing a new system on it. The partition " "can also be erased by pressing \"No\" and then deleting " "and recreating it. Are you sure you want to proceed?", 0, 0); if (button == BSDDIALOG_CANCEL) return (false); } return (true); } static int mountpoint_sorter(const void *xa, const void *xb) { struct partition_metadata *a = *(struct partition_metadata **)xa; struct partition_metadata *b = *(struct partition_metadata **)xb; if (a->fstab == NULL && b->fstab == NULL) return 0; if (a->fstab == NULL) return 1; if (b->fstab == NULL) return -1; return strcmp(a->fstab->fs_file, b->fstab->fs_file); } static int apply_changes(struct gmesh *mesh) { struct partition_metadata *md; char message[512]; int i, nitems, error, *miniperc; const char **minilabel; const char *fstab_path; FILE *fstab; struct bsddialog_conf conf; nitems = 1; /* Partition table changes */ TAILQ_FOREACH(md, &part_metadata, metadata) { if (md->newfs != NULL) nitems++; } minilabel = calloc(nitems, sizeof(const char *)); miniperc = calloc(nitems, sizeof(int)); minilabel[0] = "Writing partition tables"; miniperc[0] = BSDDIALOG_MG_INPROGRESS; i = 1; TAILQ_FOREACH(md, &part_metadata, metadata) { if (md->newfs != NULL) { char *item; item = malloc(255); sprintf(item, "Initializing %s", md->name); minilabel[i] = item; miniperc[i] = BSDDIALOG_MG_PENDING; i++; } } i = 0; bsddialog_initconf(&conf); conf.title = "Initializing"; bsddialog_mixedgauge(&conf, "Initializing file systems. Please wait.", 0, 0, i * 100 / nitems, nitems, minilabel, miniperc); gpart_commit(mesh); miniperc[i] = BSDDIALOG_MG_COMPLETED; i++; if (getenv("BSDINSTALL_LOG") == NULL) setenv("BSDINSTALL_LOG", "/dev/null", 1); TAILQ_FOREACH(md, &part_metadata, metadata) { if (md->newfs != NULL) { miniperc[i] = BSDDIALOG_MG_INPROGRESS; bsddialog_mixedgauge(&conf, "Initializing file systems. Please wait.", 0, 0, i * 100 / nitems, nitems, minilabel, miniperc); sprintf(message, "(echo %s; %s) >>%s 2>>%s", md->newfs, md->newfs, getenv("BSDINSTALL_LOG"), getenv("BSDINSTALL_LOG")); error = system(message); miniperc[i] = (error == 0) ? BSDDIALOG_MG_COMPLETED : BSDDIALOG_MG_FAILED; i++; } } bsddialog_mixedgauge(&conf, "Initializing file systems. Please wait.", 0, 0, i * 100 / nitems, nitems, minilabel, miniperc); for (i = 1; i < nitems; i++) free(__DECONST(char *, minilabel[i])); free(minilabel); free(miniperc); /* Sort filesystems for fstab so that mountpoints are ordered */ { struct partition_metadata **tobesorted; struct partition_metadata *tmp; int nparts = 0; TAILQ_FOREACH(md, &part_metadata, metadata) nparts++; tobesorted = malloc(sizeof(struct partition_metadata *)*nparts); nparts = 0; TAILQ_FOREACH_SAFE(md, &part_metadata, metadata, tmp) { tobesorted[nparts++] = md; TAILQ_REMOVE(&part_metadata, md, metadata); } qsort(tobesorted, nparts, sizeof(tobesorted[0]), mountpoint_sorter); /* Now re-add everything */ while (nparts-- > 0) TAILQ_INSERT_HEAD(&part_metadata, tobesorted[nparts], metadata); free(tobesorted); } 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)); conf.title = "Error"; bsddialog_msgbox(&conf, message, 0, 0); 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\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 void apply_workaround(struct gmesh *mesh) { struct gclass *classp; struct ggeom *gp; struct gconfig *gc; const char *scheme = NULL, *modified = NULL; struct bsddialog_conf conf; LIST_FOREACH(classp, &mesh->lg_class, lg_class) { if (strcmp(classp->lg_name, "PART") == 0) break; } if (strcmp(classp->lg_name, "PART") != 0) { bsddialog_initconf(&conf); conf.title = "Error"; bsddialog_msgbox(&conf, "gpart not found!", 0, 0); return; } LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { LIST_FOREACH(gc, &gp->lg_config, lg_config) { if (strcmp(gc->lg_name, "scheme") == 0) { scheme = gc->lg_val; } else if (strcmp(gc->lg_name, "modified") == 0) { modified = gc->lg_val; } } if (scheme && strcmp(scheme, "GPT") == 0 && modified && strcmp(modified, "true") == 0) { if (getenv("WORKAROUND_LENOVO")) gpart_set_root(gp->lg_name, "lenovofix"); if (getenv("WORKAROUND_GPTACTIVE")) gpart_set_root(gp->lg_name, "active"); } } } 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 index 5c0405922d21..aa1ec285ff80 100644 --- a/usr.sbin/bsdinstall/partedit/partedit.h +++ b/usr.sbin/bsdinstall/partedit/partedit.h @@ -1,108 +1,110 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _PARTEDIT_PARTEDIT_H #define _PARTEDIT_PARTEDIT_H #include #include #include +#include "opt_osname.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(const char *fstype); int scripted_editor(int argc, const char **argv); char *boot_disk_select(struct gmesh *mesh); int wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype, int interactive); /* gpart operations */ void gpart_delete(struct gprovider *pp); void gpart_destroy(struct ggeom *lg_geom); void gpart_edit(struct gprovider *pp); void gpart_create(struct gprovider *pp, const char *default_type, const char *default_size, const 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, const char *newfs); void gpart_set_root(const char *lg_name, const char *attribute); const char *choose_part_type(const char *def_scheme); /* machine-dependent bootability checks */ const char *default_scheme(void); /* Default partition scheme */ int is_scheme_bootable(const char *scheme); /* Non-zero if scheme boots */ int is_fs_bootable(const char *scheme, const char *fs); /* Ditto if FS boots */ /* Size of boot partition in bytes. Zero if no boot partition */ size_t bootpart_size(const char *scheme); /* * Type and mountpoint of boot partition for given scheme. If boot partition * should not be mounted, set mountpoint to NULL or leave it unchanged. * Note that mountpoint non-NULL implies partcode_path() will be ignored. * Do *NOT* set both! */ const char *bootpart_type(const char *scheme, const char **mountpoint); /* Path to bootcode that goes in the scheme (e.g. disk MBR). NULL if none */ const char *bootcode_path(const char *scheme); /* * Path to boot blocks to be dd'ed into the partition suggested by bootpart_* * for the given scheme and root filesystem type. If the boot partition should * be mounted rather than dd'ed to, return NULL here. */ const char *partcode_path(const char *scheme, const char *fs_type); #endif